X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/a0f4c418d39ab72d88e1430500082b7d6bb68073..8097430a810ac1535fe5304f74991b16ff58b064:/modules/m_kline.c diff --git a/modules/m_kline.c b/modules/m_kline.c index b1cc350..89ba235 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -71,7 +71,6 @@ DECLARE_MODULE_AV1(kline, NULL, NULL, kline_clist, NULL, NULL, "$Revision$"); static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host); static int valid_comment(struct Client *source_p, char *comment); static int valid_user_host(struct Client *source_p, const char *user, const char *host); -static int valid_wild_card(struct Client *source_p, const char *user, const char *host); static void handle_remote_kline(struct Client *source_p, int tkline_time, const char *user, const char *host, const char *reason); @@ -79,11 +78,14 @@ static void apply_kline(struct Client *source_p, struct ConfItem *aconf, const char *reason, const char *oper_reason); static void apply_tkline(struct Client *source_p, struct ConfItem *aconf, const char *, const char *, int); +static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, + const char *, const char *, int); static int already_placed_kline(struct Client *, const char *, const char *, int); static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host); static void remove_permkline_match(struct Client *, struct ConfItem *); static int remove_temp_kline(struct Client *, struct ConfItem *); +static void remove_prop_kline(struct Client *, struct ConfItem *); /* mo_kline() * @@ -105,6 +107,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char struct ConfItem *aconf; int tkline_time = 0; int loc = 1; + int propagated = ConfigFileEntry.use_propagated_bans; if(!IsOperK(source_p)) { @@ -153,17 +156,35 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char /* If we are sending it somewhere that doesnt include us, stop */ if(!match(target_server, me.name)) return 0; + + /* Set as local-only. */ + propagated = 0; } /* if we have cluster servers, send it to them.. */ - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "KLINE", (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN, "%lu %s %s :%s", tkline_time, user, host, reason); if(!valid_user_host(source_p, user, host) || - !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason)) + !valid_comment(source_p, reason)) return 0; + if(!valid_wild_card(user, host)) + { + sendto_one_notice(source_p, + ":Please include at least %d non-wildcard " + "characters with the user@host", + ConfigFileEntry.min_nonwildcard); + return 0; + } + + if(propagated && tkline_time == 0) + { + sendto_one_notice(source_p, ":Cannot set a permanent global ban"); + return 0; + } + if(already_placed_kline(source_p, user, host, tkline_time)) return 0; @@ -174,7 +195,6 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char aconf->host = rb_strdup(host); aconf->user = rb_strdup(user); aconf->port = 0; - aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ @@ -186,8 +206,11 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char if(!EmptyString(oper_reason)) aconf->spasswd = rb_strdup(oper_reason); } + aconf->passwd = rb_strdup(reason); - if(tkline_time > 0) + if(propagated) + apply_prop_kline(source_p, aconf, reason, oper_reason, tkline_time); + else if(tkline_time > 0) apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); else apply_kline(source_p, aconf, reason, oper_reason); @@ -265,9 +288,18 @@ handle_remote_kline(struct Client *source_p, int tkline_time, return; if(!valid_user_host(source_p, user, host) || - !valid_wild_card(source_p, user, host) || !valid_comment(source_p, reason)) + !valid_comment(source_p, reason)) return; + if(!valid_wild_card(user, host)) + { + sendto_one_notice(source_p, + ":Please include at least %d non-wildcard " + "characters with the user@host", + ConfigFileEntry.min_nonwildcard); + return; + } + if(already_placed_kline(source_p, user, host, tkline_time)) return; @@ -277,7 +309,6 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->created = rb_current_time(); aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); - aconf->passwd = rb_strdup(reason); aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ @@ -289,6 +320,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, if(!EmptyString(oper_reason)) aconf->spasswd = rb_strdup(oper_reason); } + aconf->passwd = rb_strdup(reason); if(tkline_time > 0) apply_tkline(source_p, aconf, reason, oper_reason, tkline_time); @@ -324,6 +356,7 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha char splat[] = "*"; char *h = LOCAL_COPY(parv[1]); struct ConfItem *aconf; + int propagated = 1; if(!IsOperUnkline(source_p)) { @@ -375,17 +408,32 @@ mo_unkline(struct Client *client_p, struct Client *source_p, int parc, const cha if(match(parv[3], me.name) == 0) return 0; + + propagated = 0; } - else if(rb_dlink_list_length(&cluster_conf_list) > 0) + + aconf = find_exact_conf_by_address(host, CONF_KILL, user); + + /* No clustering for removing a propagated kline */ + if(propagated && (aconf == NULL || !aconf->lifetime) && + rb_dlink_list_length(&cluster_conf_list) > 0) cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN, "%s %s", user, host); - aconf = find_exact_conf_by_address(host, CONF_KILL, user); if(aconf == NULL) { sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); return 0; } + + if(aconf->lifetime) + { + if(propagated) + remove_prop_kline(source_p, aconf); + else + sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); + return 0; + } if(remove_temp_kline(source_p, aconf)) return 0; @@ -444,6 +492,11 @@ handle_remote_unkline(struct Client *source_p, const char *user, const char *hos sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); return; } + if(aconf->lifetime) + { + sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); + return; + } if(remove_temp_kline(source_p, aconf)) return; @@ -527,6 +580,54 @@ apply_tkline(struct Client *source_p, struct ConfItem *aconf, tkline_time / 60, aconf->user, aconf->host); } +static void +apply_prop_kline(struct Client *source_p, struct ConfItem *aconf, + const char *reason, const char *oper_reason, int tkline_time) +{ + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + aconf->hold = rb_current_time() + tkline_time; + aconf->lifetime = aconf->hold; + + replace_old_ban(aconf); + + rb_dlinkAddAlloc(aconf, &prop_bans); + add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); + + /* no oper reason.. */ + if(EmptyString(oper_reason)) + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. K-Line for [%s@%s] [%s]", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason); + ilog(L_KLINE, "K %s %d %s %s %s", + get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason); + } + else + { + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s added global %d min. K-Line for [%s@%s] [%s|%s]", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason, oper_reason); + ilog(L_KLINE, "K %s %d %s %s %s|%s", + get_oper_name(source_p), tkline_time / 60, + aconf->user, aconf->host, reason, oper_reason); + } + + sendto_one_notice(source_p, ":Added global %d min. K-Line [%s@%s]", + tkline_time / 60, aconf->user, aconf->host); + + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN K %s %s %lu %d %d * :%s%s%s", + source_p->id, aconf->user, aconf->host, + (unsigned long)aconf->created, + (int)(aconf->hold - aconf->created), + (int)(aconf->lifetime - aconf->created), + reason, + oper_reason ? "|" : "", + oper_reason ? oper_reason : ""); +} + /* find_user_host() * * inputs - client placing kline, user@host, user buffer, host buffer @@ -590,65 +691,6 @@ valid_user_host(struct Client *source_p, const char *luser, const char *lhost) return 1; } -/* valid_wild_card() - * - * input - user buffer, host buffer - * output - 0 if invalid, 1 if valid - * side effects - - */ -static int -valid_wild_card(struct Client *source_p, const char *luser, const char *lhost) -{ - const char *p; - char tmpch; - int nonwild = 0; - int bitlen; - - /* user has no wildcards, always accept -- jilles */ - if(!strchr(luser, '?') && !strchr(luser, '*')) - return 1; - - /* check there are enough non wildcard chars */ - p = luser; - while((tmpch = *p++)) - { - if(!IsKWildChar(tmpch)) - { - /* found enough chars, return */ - if(++nonwild >= ConfigFileEntry.min_nonwildcard) - return 1; - } - } - - /* try host, as user didnt contain enough */ - /* special case for cidr masks -- jilles */ - if((p = strrchr(lhost, '/')) != NULL && IsDigit(p[1])) - { - bitlen = atoi(p + 1); - /* much like non-cidr for ipv6, rather arbitrary for ipv4 */ - if(bitlen > 0 - && bitlen >= - (strchr(lhost, ':') ? 4 * (ConfigFileEntry.min_nonwildcard - nonwild) : 6 - - 2 * nonwild)) - return 1; - } - else - { - p = lhost; - while((tmpch = *p++)) - { - if(!IsKWildChar(tmpch)) - if(++nonwild >= ConfigFileEntry.min_nonwildcard) - return 1; - } - } - - sendto_one_notice(source_p, - ":Please include at least %d non-wildcard " - "characters with the user@host", ConfigFileEntry.min_nonwildcard); - return 0; -} - /* * valid_comment * inputs - pointer to client @@ -799,3 +841,39 @@ remove_temp_kline(struct Client *source_p, struct ConfItem *aconf) return NO; } + +static void +remove_prop_kline(struct Client *source_p, struct ConfItem *aconf) +{ + rb_dlink_node *ptr; + + ptr = rb_dlinkFind(aconf, &prop_bans); + if (!ptr) + return; + sendto_one_notice(source_p, + ":Un-klined [%s@%s] from global k-lines", + aconf->user, aconf->host); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "%s has removed the global K-Line for: [%s@%s]", + get_oper_name(source_p), aconf->user, + aconf->host); + + ilog(L_KLINE, "UK %s %s %s", + get_oper_name(source_p), aconf->user, aconf->host); + if(aconf->created < rb_current_time()) + aconf->created = rb_current_time(); + else + aconf->created++; + aconf->hold = aconf->created; + operhash_delete(aconf->info.oper); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY; + sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS, + ":%s BAN K %s %s %lu %d %d * :*", + source_p->id, aconf->user, aconf->host, + (unsigned long)aconf->created, + 0, + (int)(aconf->lifetime - aconf->created)); + remove_reject_mask(aconf->user, aconf->host); + deactivate_conf(aconf, ptr); +}