unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

msgbypass.c (6329B)

      1 /*
      2  * Extended ban that allows user to bypass message restrictions
      3  * (C) Copyright 2017-.. Bram Matthys (Syzop) and the UnrealIRCd team
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 1, or (at your option)
      8  * any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 #include "unrealircd.h"
     20 
     21 ModuleHeader MOD_HEADER
     22 = {
     23 	"extbans/msgbypass",
     24 	"4.2",
     25 	"ExtBan ~m - bypass +m/+n/+c/+S/+T (msgbypass)",
     26 	"UnrealIRCd Team",
     27 	"unrealircd-6",
     28 };
     29 
     30 /* Forward declarations */
     31 int msgbypass_can_bypass(Client *client, Channel *channel, BypassChannelMessageRestrictionType bypass_type);
     32 int msgbypass_extban_is_ok(BanContext *b);
     33 const char *msgbypass_extban_conv_param(BanContext *b, Extban *extban);
     34 
     35 /** Called upon module init */
     36 MOD_INIT()
     37 {
     38 	ExtbanInfo req;
     39 	
     40 	memset(&req, 0, sizeof(req));
     41 	req.letter = 'm';
     42 	req.name = "msgbypass";
     43 	req.is_ok = msgbypass_extban_is_ok;
     44 	req.conv_param = msgbypass_extban_conv_param;
     45 	req.options = EXTBOPT_ACTMODIFIER;
     46 	if (!ExtbanAdd(modinfo->handle, req))
     47 	{
     48 		config_error("could not register extended ban type ~m");
     49 		return MOD_FAILED;
     50 	}
     51 
     52 	MARK_AS_OFFICIAL_MODULE(modinfo);
     53 	
     54 	return MOD_SUCCESS;
     55 }
     56 
     57 /** Called upon module load */
     58 MOD_LOAD()
     59 {
     60 	HookAdd(modinfo->handle, HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION, 0, msgbypass_can_bypass);
     61 	return MOD_SUCCESS;
     62 }
     63 
     64 /** Called upon unload */
     65 MOD_UNLOAD()
     66 {
     67 	return MOD_SUCCESS;
     68 }
     69 
     70 /** Can the user bypass restrictions? */
     71 int msgbypass_can_bypass(Client *client, Channel *channel, BypassChannelMessageRestrictionType bypass_type)
     72 {
     73 	Ban *ban;
     74 	char *p;
     75 	BanContext *b = safe_alloc(sizeof(BanContext));
     76 
     77 	b->client = client;
     78 	b->channel = channel;
     79 	b->ban_check_types = BANCHK_MSG;
     80 
     81 	for (ban = channel->exlist; ban; ban=ban->next)
     82 	{
     83 		char *type;
     84 		char *matchby;
     85 
     86 		if (!strncmp(ban->banstr, "~m:", 3))
     87 			type = ban->banstr + 3;
     88 		else if (!strncmp(ban->banstr, "~msgbypass:", 11))
     89 			type = ban->banstr + 11;
     90 		else
     91 			continue;
     92 
     93 		if (((bypass_type == BYPASS_CHANMSG_EXTERNAL) && !strncmp(type, "external:", 9)) ||
     94 		    ((bypass_type == BYPASS_CHANMSG_MODERATED) && !strncmp(type, "moderated:", 10)) ||
     95 		    ((bypass_type == BYPASS_CHANMSG_COLOR) && !strncmp(type, "color:", 6)) ||
     96 		    ((bypass_type == BYPASS_CHANMSG_CENSOR) && !strncmp(type, "censor:", 7)) ||
     97 		    ((bypass_type == BYPASS_CHANMSG_NOTICE) && !strncmp(type, "notice:", 7)))
     98 		{
     99 			matchby = strchr(type, ':');
    100 			if (!matchby)
    101 				continue;
    102 			matchby++;
    103 			
    104 			b->banstr = matchby;
    105 			if (ban_check_mask(b))
    106 			{
    107 				safe_free(b);
    108 				return HOOK_ALLOW; /* Yes, user may bypass */
    109 			}
    110 		}
    111 	}
    112 
    113 	safe_free(b);
    114 	return HOOK_CONTINUE; /* No, may NOT bypass. */
    115 }
    116 
    117 /** Does this bypass type exist? (eg: 'external') */
    118 int msgbypass_extban_type_ok(char *type)
    119 {
    120 	if (!strcmp(type, "external") ||
    121 	    !strcmp(type, "moderated") ||
    122 	    !strcmp(type, "censor") ||
    123 	    !strcmp(type, "color") ||
    124 	    !strcmp(type, "notice"))
    125 	{
    126 		return 1; /* Yes, OK type */
    127 	}
    128 	return 0; /* NOMATCH */
    129 }
    130 
    131 #define MAX_LENGTH 128
    132 const char *msgbypass_extban_conv_param(BanContext *b, Extban *extban)
    133 {
    134 	static char retbuf[MAX_LENGTH+1];
    135 	char para[MAX_LENGTH+1];
    136 	char tmpmask[MAX_LENGTH+1];
    137 	char *type; /**< Type, such as 'external' */
    138 	char *matchby; /**< Matching method, such as 'n!u@h' */
    139 	const char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
    140 
    141 	strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
    142 	
    143 	/* ~m:type:n!u@h   for direct matching
    144 	 * ~m:type:~x:.... when calling another bantype
    145 	 */
    146 
    147 	type = para;
    148 	matchby = strchr(para, ':');
    149 	if (!matchby || !matchby[1])
    150 		return NULL;
    151 	*matchby++ = '\0';
    152 
    153 	if (!msgbypass_extban_type_ok(type))
    154 		return NULL;
    155 
    156 	b->banstr = matchby;
    157 	newmask = extban_conv_param_nuh_or_extban(b, extban);
    158 	if (BadPtr(newmask))
    159 		return NULL;
    160 
    161 	//snprintf(retbuf, sizeof(retbuf), "~m:%s:%s", type, newmask);
    162 	snprintf(retbuf, sizeof(retbuf), "%s:%s", type, newmask);
    163 	return retbuf;
    164 }
    165 
    166 int msgbypass_extban_syntax(Client *client, int checkt, char *reason)
    167 {
    168 	if (MyUser(client) && (checkt == EXBCHK_PARAM))
    169 	{
    170 		sendnotice(client, "Error when setting ban exception: %s", reason);
    171 		sendnotice(client, " Syntax: +e ~m:type:mask");
    172 		sendnotice(client, "Example: +e ~m:moderated:~a:TrustedUser");
    173 		sendnotice(client, "Valid types are: external, moderated, color, notice");
    174 		sendnotice(client, "Valid masks are: nick!user@host or another extban type such as ~a, ~c, ~S, ..");
    175 	}
    176 	return 0; /* FAIL: ban rejected */
    177 }
    178 
    179 int msgbypass_extban_is_ok(BanContext *b)
    180 {
    181 	static char para[MAX_LENGTH+1];
    182 	char *type; /**< Type, such as 'external' */
    183 	char *matchby; /**< Matching method, such as 'n!u@h' */
    184 	char *newmask; /**< Cleaned matching method, such as 'n!u@h' */
    185 
    186 	/* Always permit deletion */
    187 	if (b->what == MODE_DEL)
    188 		return 1;
    189 	
    190 	if (b->ban_type != EXBTYPE_EXCEPT)
    191 	{
    192 		if (b->is_ok_check == EXBCHK_PARAM)
    193 			sendnotice(b->client, "Ban type ~m only works with exceptions (+e) and not with bans or invex (+b/+I)");
    194 		return 0; /* reject */
    195 	}
    196 
    197 	strlcpy(para, b->banstr, sizeof(para)); /* work on a copy (and truncate it) */
    198 	
    199 	/* ~m:type:n!u@h   for direct matching
    200 	 * ~m:type:~x:.... when calling another bantype
    201 	 */
    202 
    203 	type = para;
    204 	matchby = strchr(para, ':');
    205 	if (!matchby || !matchby[1])
    206 		return msgbypass_extban_syntax(b->client, b->is_ok_check, "Invalid syntax");
    207 	*matchby++ = '\0';
    208 
    209 	if (!msgbypass_extban_type_ok(type))
    210 		return msgbypass_extban_syntax(b->client, b->is_ok_check, "Unknown type");
    211 
    212 	b->banstr = matchby;
    213 	if (extban_is_ok_nuh_extban(b) == 0)
    214 	{
    215 		/* This could be anything ranging from:
    216 		 * invalid n!u@h syntax, unknown (sub)extbantype,
    217 		 * disabled extban type in conf, too much recursion, etc.
    218 		 */
    219 		return msgbypass_extban_syntax(b->client, b->is_ok_check, "Invalid matcher");
    220 	}
    221 
    222 	return 1; /* OK */
    223 }
    224