From c604a3a70ef7b6457f0d2bd9db69e87166b100cf Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sun, 5 Dec 2021 09:45:13 +0100 Subject: [PATCH] Make soft extended server bans actually work (GLINE %~country:XX) Reported by musk in https://bugs.unrealircd.org/view.php?id=6019 --- include/h.h | 1 + src/channel.c | 16 ++++++++++++++++ src/modules/tkl.c | 30 ++++++++++++++++++++---------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/include/h.h b/include/h.h index 4e47fd0c3..3cb2f578e 100644 --- a/include/h.h +++ b/include/h.h @@ -1031,6 +1031,7 @@ extern void short_motd(Client *client); extern int should_show_connect_info(Client *client); extern void send_invalid_channelname(Client *client, const char *channelname); extern int is_extended_ban(const char *str); +extern int is_extended_server_ban(const char *str); extern int empty_mode(const char *m); extern void free_multilinemode(MultiLineMode *m); #define safe_free_multilinemode(m) do { if (m) free_multilinemode(m); m = NULL; } while(0) diff --git a/src/channel.c b/src/channel.c index 529c8a072..a465f20e6 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1293,6 +1293,7 @@ void send_invalid_channelname(Client *client, const char *channelname) /** Is the provided string possibly an extended ban? * Note that it still may not exist, it just tests the first part. + * @param str The string to check (eg "~account:xyz") */ int is_extended_ban(const char *str) { @@ -1311,6 +1312,21 @@ int is_extended_ban(const char *str) return 0; } +/** Is the provided string possibly an extended server ban? + * Actually this is only a very light check. + * It may still not exist, it just tests the first part. + * @param str The string to check (eg "~account:xyz") + * The only difference between this and is_extended_ban() + * is that we allow a % at the beginning for soft-bans. + * @see is_extended_ban() + */ +int is_extended_server_ban(const char *str) +{ + if (*str == '%') + str++; + return is_extended_ban(str); +} + /** Check if it is an empty (useless) mode, namely "", "+" or "-". * Typically called as: empty_mode(modebuf) */ diff --git a/src/modules/tkl.c b/src/modules/tkl.c index f57271a2c..71e929253 100644 --- a/src/modules/tkl.c +++ b/src/modules/tkl.c @@ -609,7 +609,7 @@ int tkl_config_run_ban(ConfigFile *cf, ConfigEntry *ce, int configtype) { if (!strcmp(cep->name, "mask")) { - if (is_extended_ban(cep->value)) + if (is_extended_server_ban(cep->value)) { char mask1buf[512], mask2buf[512]; char *err = NULL; @@ -791,7 +791,7 @@ void config_create_tkl_except(char *mask, char *bantypes) mask++; } strlcpy(buf, mask, sizeof(buf)); - if (is_extended_ban(buf)) + if (is_extended_server_ban(buf)) { char *err = NULL; if (!parse_extended_server_ban(buf, NULL, &err, 0, mask1buf, sizeof(mask1buf), mask2buf, sizeof(mask2buf))) @@ -1288,13 +1288,20 @@ int parse_extended_server_ban(const char *mask_in, Client *client, char **error, BanContext *b = NULL; char mask[USERLEN + NICKLEN + HOSTLEN + 32]; // same as extban_conv_param_nuh_or_extban() char newmask[USERLEN + NICKLEN + HOSTLEN + 32]; + char soft_ban = 0; *error = NULL; if (buf1 && buf2) *buf1 = *buf2 = '\0'; /* Work on a copy */ - strlcpy(mask, mask_in, sizeof(mask)); + if (*mask_in == '%') + { + strlcpy(mask, mask_in+1, sizeof(mask)); + soft_ban = 1; + } else { + strlcpy(mask, mask_in, sizeof(mask)); + } extban = findmod_by_bantype(mask, &nextbanstr); if (!extban || !(extban->options & EXTBOPT_TKL)) @@ -1360,7 +1367,10 @@ int parse_extended_server_ban(const char *mask_in, Client *client, char **error, p++; save = *p; *p = '\0'; - strlcpy(buf1, newmask, buf1len); /* eg ~S: */ + /* First buffer is eg ~S: or %~S: */ + snprintf(buf1, buf1len, "%s%s", + soft_ban ? "%" : "", + newmask); *p = save; strlcpy(buf2, p, buf2len); /* eg 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef */ } @@ -1445,7 +1455,7 @@ void cmd_tkl_line(Client *client, int parc, const char *parv[], char *type) } /* Check if it's an extended server ban */ - if (is_extended_ban(mask)) + if (is_extended_server_ban(mask)) { char *err; @@ -1754,7 +1764,7 @@ CMD_FUNC(cmd_eline) return; /* Check if it's an extended server ban */ - if (is_extended_ban(mask)) + if (is_extended_server_ban(mask)) { char *err; if (!parse_extended_server_ban(mask, client, &err, 0, mask1buf, sizeof(mask1buf), mask2buf, sizeof(mask2buf))) @@ -2830,7 +2840,7 @@ char *_tkl_uhost(TKL *tkl, char *buf, size_t buflen, int options) { if (TKLIsServerBan(tkl)) { - if (is_extended_ban(tkl->ptr.serverban->usermask)) + if (is_extended_server_ban(tkl->ptr.serverban->usermask)) { ircsnprintf(buf, buflen, "%s%s%s", (!(options & NO_SOFT_PREFIX) && (tkl->ptr.serverban->subtype & TKL_SUBTYPE_SOFT)) ? "%" : "", @@ -2843,7 +2853,7 @@ char *_tkl_uhost(TKL *tkl, char *buf, size_t buflen, int options) } else if (TKLIsBanException(tkl)) { - if (is_extended_ban(tkl->ptr.banexception->usermask)) + if (is_extended_server_ban(tkl->ptr.banexception->usermask)) { ircsnprintf(buf, buflen, "%s%s%s", (!(options & NO_SOFT_PREFIX) && (tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT)) ? "%" : "", @@ -5013,7 +5023,7 @@ int _match_user(const char *rmask, Client *client, int options) strlcpy(mask, rmask, sizeof(mask)); if ((options & MATCH_CHECK_EXTENDED) && - is_extended_ban(mask) && + is_extended_server_ban(mask) && client->user) { /* Check user properties / extbans style */ @@ -5163,7 +5173,7 @@ int _match_user_extended_server_ban(const char *banstr, Client *client) BanContext *b; int ret; - if (!is_extended_ban(banstr)) + if (!is_extended_server_ban(banstr)) return 0; /* we should never have been called */ extban = findmod_by_bantype(banstr, &nextbanstr);