unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
flood.c (5219B)
1 /* 2 * Extended ban to exempt from +f/+F checking. 3 * Eg: +e ~flood:*:~account:TrustedBot 4 * (C) Copyright 2023-.. Bram Matthys (Syzop) and the UnrealIRCd team 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 1, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 #include "unrealircd.h" 21 22 ModuleHeader MOD_HEADER 23 = { 24 "extbans/flood", 25 "1.0", 26 "Extban ~flood - exempt from +f/+F checks", 27 "UnrealIRCd Team", 28 "unrealircd-6", 29 }; 30 31 /** Maximum length of the ~flood ban exemption */ 32 #define MAX_FLOODBAN_LENGTH 128 33 34 /* Forward declarations */ 35 int extban_flood_is_banned(BanContext *b); 36 int flood_extban_is_ok(BanContext *b); 37 const char *flood_extban_conv_param(BanContext *b, Extban *extban); 38 39 /** Called upon module init */ 40 MOD_INIT() 41 { 42 ExtbanInfo req; 43 44 memset(&req, 0, sizeof(req)); 45 req.letter = 'F'; 46 req.name = "flood"; 47 req.is_ok = flood_extban_is_ok; 48 req.conv_param = flood_extban_conv_param; 49 req.options = EXTBOPT_ACTMODIFIER; 50 if (!ExtbanAdd(modinfo->handle, req)) 51 { 52 config_error("could not register extended ban type 'flood'"); 53 return MOD_FAILED; 54 } 55 56 MARK_AS_OFFICIAL_MODULE(modinfo); 57 58 return MOD_SUCCESS; 59 } 60 61 /** Called upon module load */ 62 MOD_LOAD() 63 { 64 return MOD_SUCCESS; 65 } 66 67 /** Called upon unload */ 68 MOD_UNLOAD() 69 { 70 return MOD_SUCCESS; 71 } 72 73 /** Check if letters in 'str' are valid flood-types. 74 * TODO: ideally this would call a function in chanmode +F module!! 75 */ 76 static int flood_type_ok(char *str) 77 { 78 char *p; 79 80 /* The * (asterisk) simply means ALL. */ 81 if (!strcmp(str, "*")) 82 return 1; 83 84 for (p = str; *p; p++) 85 if (!strchr("cjkmntr", *p)) 86 return 0; 87 88 return 1; 89 } 90 91 const char *flood_extban_conv_param(BanContext *b, Extban *extban) 92 { 93 static char retbuf[MAX_FLOODBAN_LENGTH+1]; 94 char para[MAX_FLOODBAN_LENGTH+1]; 95 char tmpmask[MAX_FLOODBAN_LENGTH+1]; 96 char *type; /**< Type(s), such as 'j' */ 97 char *matchby; /**< Matching method, such as 'n!u@h' */ 98 const char *newmask; /**< Cleaned matching method, such as 'n!u@h' */ 99 100 strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */ 101 102 /* ~flood:type:n!u@h for direct matching 103 * ~flood:type:~x:.... when calling another bantype 104 */ 105 106 type = para; 107 matchby = strchr(para, ':'); 108 if (!matchby || !matchby[1]) 109 return NULL; 110 *matchby++ = '\0'; 111 112 /* don't verify type(s), already done in is_ok for local clients */ 113 //if (!flood_type_ok(type)) 114 // return NULL; 115 /* ... but limit them to a reasonable value :D */ 116 if (strlen(type) > 16) 117 return NULL; 118 119 b->banstr = matchby; 120 newmask = extban_conv_param_nuh_or_extban(b, extban); 121 if (BadPtr(newmask)) 122 return NULL; 123 124 snprintf(retbuf, sizeof(retbuf), "%s:%s", type, newmask); 125 return retbuf; 126 } 127 128 int flood_extban_syntax(Client *client, int checkt, char *reason) 129 { 130 if (MyUser(client) && (checkt == EXBCHK_PARAM)) 131 { 132 sendnotice(client, "Error when setting ban exception: %s", reason); 133 sendnotice(client, " Syntax: +e ~flood:floodtype(s):mask"); 134 sendnotice(client, "Example: +e ~flood:*:~account:TrustedUser"); 135 sendnotice(client, "Valid flood types are: c, j, k, m, n, t, r, and * for all"); 136 sendnotice(client, "Valid masks are: nick!user@host or another extban type such as ~account, ~certfp, etc."); 137 } 138 return 0; /* FAIL: ban rejected */ 139 } 140 141 int flood_extban_is_ok(BanContext *b) 142 { 143 static char para[MAX_FLOODBAN_LENGTH+1]; 144 char *type; /**< Type(s), such as 'j' */ 145 char *matchby; /**< Matching method, such as 'n!u@h' */ 146 char *newmask; /**< Cleaned matching method, such as 'n!u@h' */ 147 148 /* Always permit deletion */ 149 if (b->what == MODE_DEL) 150 return 1; 151 152 if (b->ban_type != EXBTYPE_EXCEPT) 153 { 154 if (b->is_ok_check == EXBCHK_PARAM) 155 sendnotice(b->client, "Ban type ~flood only works with exceptions (+e) and not with bans or invex (+b/+I)"); 156 return 0; /* reject */ 157 } 158 159 strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */ 160 161 /* ~flood:type:n!u@h for direct matching 162 * ~flood:type:~x:.... when calling another bantype 163 */ 164 165 type = para; 166 matchby = strchr(para, ':'); 167 if (!matchby || !matchby[1]) 168 return flood_extban_syntax(b->client, b->is_ok_check, "Invalid syntax"); 169 *matchby++ = '\0'; 170 171 if (!flood_type_ok(type)) 172 return flood_extban_syntax(b->client, b->is_ok_check, "Unknown flood type"); 173 if (strlen(type) > 16) 174 return flood_extban_syntax(b->client, b->is_ok_check, "Too many flood types specified"); 175 176 b->banstr = matchby; 177 if (extban_is_ok_nuh_extban(b) == 0) 178 { 179 /* This could be anything ranging from: 180 * invalid n!u@h syntax, unknown (sub)extbantype, 181 * disabled extban type in conf, too much recursion, etc. 182 */ 183 return flood_extban_syntax(b->client, b->is_ok_check, "Invalid matcher"); 184 } 185 186 return 1; /* OK */ 187 }