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