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 }