From aec54db360257bc45a230e9bc212ee0b3b57f2d2 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Fri, 11 Oct 2019 11:17:50 +0200 Subject: [PATCH] Add is_extended_ban() which does a quick check for "~x:". This, rather than scattered checks - which are sometimes different - everywhere in the source code. Also extban handler "is_ok" was being called with EXBTYPE_EXCEPT rather than EXBTYPE_INVEX for +I. (Not reported by anyone) --- include/h.h | 1 + src/api-extban.c | 4 +-- src/channel.c | 16 +++++++++-- src/modules/extbans/msgbypass.c | 2 +- src/modules/extbans/timedban.c | 51 ++++++++++++++++----------------- src/modules/mode.c | 39 ++++++++++++++++++------- 6 files changed, 70 insertions(+), 43 deletions(-) diff --git a/include/h.h b/include/h.h index 8b54f3752..d4ab2229b 100644 --- a/include/h.h +++ b/include/h.h @@ -950,3 +950,4 @@ extern MODVAR int non_utf8_nick_chars_in_use; extern void short_motd(Client *client); extern int should_show_connect_info(Client *client); extern void send_invalid_channelname(Client *client, char *channelname); +extern int is_extended_ban(const char *str); diff --git a/src/api-extban.c b/src/api-extban.c index d1ec62dec..e168492d9 100644 --- a/src/api-extban.c +++ b/src/api-extban.c @@ -130,7 +130,7 @@ int extban_is_ok_nuh_extban(Client* client, Channel* channel, char* para, int ch static int extban_is_ok_recursion = 0; /* Mostly copied from clean_ban_mask - but note MyUser checks aren't needed here: extban->is_ok() according to cmd_mode isn't called for nonlocal. */ - if ((*mask == '~') && mask[1] && (mask[2] == ':')) + if (is_extended_ban(mask)) { if (extban_is_ok_recursion) return 0; /* Fail: more than one stacked extban */ @@ -217,7 +217,7 @@ char* extban_conv_param_nuh_or_extban(char* para) Extban *p = NULL; static int extban_recursion = 0; - if (para[3] == '~' && para[4] && para[5] == ':') + if (is_extended_ban(para+3)) { /* We're dealing with a stacked extended ban. * Rules: diff --git a/src/channel.c b/src/channel.c index 3880d2e1c..6a689fdb1 100644 --- a/src/channel.c +++ b/src/channel.c @@ -232,7 +232,7 @@ Client *find_chasing(Client *client, char *user, int *chasing) /** Return 1 if the bans are identical, taking into account special handling for extbans */ int identical_ban(char *one, char *two) { - if ((*one == '~') && (strlen(one) > 3)) + if (is_extended_ban(one)) { /* compare the first 3 characters case-sensitive and if identical then compare * the remainder of the string case-insensitive. @@ -393,7 +393,7 @@ inline Ban *is_banned(Client *client, Channel *channel, int type, char **msg, ch inline int ban_check_mask(Client *client, Channel *channel, char *banstr, int type, char **msg, char **errmsg, int no_extbans) { Extban *extban = NULL; - if (!no_extbans && banstr[0] == '~' && banstr[1] != '\0' && banstr[2] == ':') + if (!no_extbans && is_extended_ban(banstr)) { /* Is an extended ban. */ extban = findmod_by_bantype(banstr[1]); @@ -791,7 +791,7 @@ char *clean_ban_mask(char *mask, int what, Client *client) return NULL; /* Extended ban? */ - if ((*mask == '~') && mask[1] && (mask[2] == ':')) + if (is_extended_ban(mask)) { if (RESTRICT_EXTENDEDBANS && MyUser(client) && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,NULL,NULL)) { @@ -1393,3 +1393,13 @@ void send_invalid_channelname(Client *client, char *channelname) sendnumeric(client, ERR_FORBIDDENCHANNEL, channelname, reason); } + +/** Is the provided string possibly an extended ban? + * Note that it still may not exist, it just tests the first part. + */ +int is_extended_ban(const char *str) +{ + if ((str[0] == '~') && (str[1] != '\0') && (str[2] == ':')) + return 1; + return 0; +} diff --git a/src/modules/extbans/msgbypass.c b/src/modules/extbans/msgbypass.c index 4bc0166a6..146744dc3 100644 --- a/src/modules/extbans/msgbypass.c +++ b/src/modules/extbans/msgbypass.c @@ -81,7 +81,7 @@ int msgbypass_can_bypass(Client *client, Channel *channel, BypassChannelMessageR for (ban = channel->exlist; ban; ban=ban->next) { - if ((ban->banstr[0] == '~') && (ban->banstr[1] == 'm') && (ban->banstr[2] == ':')) + if (!strncmp(ban->banstr, "~m:", 3)) { char *type = ban->banstr + 3; char *matchby; diff --git a/src/modules/extbans/timedban.c b/src/modules/extbans/timedban.c index ae9b8190a..7efdfcac9 100644 --- a/src/modules/extbans/timedban.c +++ b/src/modules/extbans/timedban.c @@ -134,7 +134,7 @@ char *generic_clean_ban_mask(char *mask) return NULL; /* Extended ban? */ - if ((*mask == '~') && mask[1] && (mask[2] == ':')) + if (is_extended_ban(mask)) { p = findmod_by_bantype(mask[1]); if (!p) @@ -233,7 +233,7 @@ int generic_ban_is_ok(Client *client, Channel *channel, char *mask, int checkt, Extban *p; /* This portion is copied from clean_ban_mask() */ - if (mask[1] && (mask[2] == ':') && + if (is_extended_ban(mask) && RESTRICT_EXTENDEDBANS && MyUser(client) && !ValidatePermissionsForPath("immune:restrict-extendedbans",client,NULL,NULL,NULL)) { @@ -249,36 +249,33 @@ int generic_ban_is_ok(Client *client, Channel *channel, char *mask, int checkt, sendnotice(client, "Setting/removing of extended bantypes '%s' has been disabled", RESTRICT_EXTENDEDBANS); return 0; /* REJECT */ } - } - /* End of portion */ - - /* This portion is inspired by cmd_mode */ - p = findmod_by_bantype(mask[1]); - if (checkt == EXBCHK_ACCESS) - { - if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) && - !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL)) + /* And next is inspired by cmd_mode */ + p = findmod_by_bantype(mask[1]); + if (checkt == EXBCHK_ACCESS) { - return 0; /* REJECT */ - } - } else - if (checkt == EXBCHK_ACCESS_ERR) - { - if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) && - !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL)) + if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) && + !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL)) + { + return 0; /* REJECT */ + } + } else + if (checkt == EXBCHK_ACCESS_ERR) { - p->is_ok(client, channel, mask, EXBCHK_ACCESS_ERR, what, what2); - return 0; /* REJECT */ - } - } else - if (checkt == EXBCHK_PARAM) - { - if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_PARAM, what, what2)) + if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_ACCESS, what, what2) && + !ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL)) + { + p->is_ok(client, channel, mask, EXBCHK_ACCESS_ERR, what, what2); + return 0; /* REJECT */ + } + } else + if (checkt == EXBCHK_PARAM) { - return 0; /* REJECT */ + if (p && p->is_ok && !p->is_ok(client, channel, mask, EXBCHK_PARAM, what, what2)) + { + return 0; /* REJECT */ + } } } - /* End of portion */ } /* ACCEPT: diff --git a/src/modules/mode.c b/src/modules/mode.c index 33fb25be5..91bc50c15 100644 --- a/src/modules/mode.c +++ b/src/modules/mode.c @@ -1056,8 +1056,8 @@ process_listmode: tmpstr = clean_ban_mask(param, what, client); if (BadPtr(tmpstr)) { - /* Invalid ban. See if we can send an error about that */ - if ((param[0] == '~') && MyUser(client) && !bounce && (strlen(param) > 2)) + /* Invalid ban. See if we can send an error about that (only for extbans) */ + if (MyUser(client) && !bounce && is_extended_ban(param)) { Extban *p = findmod_by_bantype(param[1]); if (p && p->is_ok) @@ -1066,7 +1066,7 @@ process_listmode: break; /* ignore ban, but eat param */ } - if ((tmpstr[0] == '~') && MyUser(client) && !bounce) + if (MyUser(client) && !bounce && is_extended_ban(param)) { /* extban: check access if needed */ Extban *p = findmod_by_bantype(tmpstr[1]); @@ -1104,8 +1104,18 @@ process_listmode: REQUIRE_PARAMETER() tmpstr = clean_ban_mask(param, what, client); if (BadPtr(tmpstr)) + { + /* Invalid except. See if we can send an error about that (only for extbans) */ + if (MyUser(client) && !bounce && is_extended_ban(param)) + { + Extban *p = findmod_by_bantype(param[1]); + if (p && p->is_ok) + p->is_ok(client, channel, param, EXBCHK_PARAM, what, EXBTYPE_EXCEPT); + } + break; /* ignore except, but eat param */ - if ((tmpstr[0] == '~') && MyUser(client) && !bounce && (strlen(param) > 2)) + } + if (MyUser(client) && !bounce && is_extended_ban(param)) { /* extban: check access if needed */ Extban *p = findmod_by_bantype(tmpstr[1]); @@ -1143,8 +1153,18 @@ process_listmode: REQUIRE_PARAMETER() tmpstr = clean_ban_mask(param, what, client); if (BadPtr(tmpstr)) - break; /* ignore except, but eat param */ - if ((tmpstr[0] == '~') && MyUser(client) && !bounce && (strlen(param) > 2)) + { + /* Invalid invex. See if we can send an error about that (only for extbans) */ + if (MyUser(client) && !bounce && is_extended_ban(param)) + { + Extban *p = findmod_by_bantype(param[1]); + if (p && p->is_ok) + p->is_ok(client, channel, param, EXBCHK_PARAM, what, EXBTYPE_INVEX); + } + + break; /* ignore invex, but eat param */ + } + if (MyUser(client) && !bounce && is_extended_ban(param)) { /* extban: check access if needed */ Extban *p = findmod_by_bantype(tmpstr[1]); @@ -1152,18 +1172,17 @@ process_listmode: { if (!(p->options & EXTBOPT_INVEX)) break; /* this extended ban type does not support INVEX */ - - if (p->is_ok && !p->is_ok(client, channel, tmpstr, EXBCHK_ACCESS, what, EXBTYPE_EXCEPT)) + if (p->is_ok && !p->is_ok(client, channel, tmpstr, EXBCHK_ACCESS, what, EXBTYPE_INVEX)) { if (ValidatePermissionsForPath("channel:override:mode:extban",client,NULL,channel,NULL)) { /* TODO: send operoverride notice */ } else { - p->is_ok(client, channel, tmpstr, EXBCHK_ACCESS_ERR, what, EXBTYPE_EXCEPT); + p->is_ok(client, channel, tmpstr, EXBCHK_ACCESS_ERR, what, EXBTYPE_INVEX); break; } } - if (p->is_ok && !p->is_ok(client, channel, tmpstr, EXBCHK_PARAM, what, EXBTYPE_EXCEPT)) + if (p->is_ok && !p->is_ok(client, channel, tmpstr, EXBCHK_PARAM, what, EXBTYPE_INVEX)) break; } }