Allow temporary K-lines to extend shorter ones (#142)

* Temp K-lines may extend shorter temp K-lines

* /unkline removes multiple matching K-lines

* K-lines remove any temp K-lines they're replacing
This commit is contained in:
Ed Kellett 2021-04-27 14:45:04 +01:00 committed by GitHub
parent 788e1a98f0
commit 3ff5a12e75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 100 additions and 42 deletions

View file

@ -46,6 +46,8 @@ struct ConfItem *find_conf_by_address(const char *host, const char *sockhost,
int, int, const char *, const char *); int, int, const char *, const char *);
struct ConfItem *find_exact_conf_by_address(const char *address, int type, struct ConfItem *find_exact_conf_by_address(const char *address, int type,
const char *username); const char *username);
struct ConfItem *find_exact_conf_by_address_filtered(const char *address, int type,
const char *username, bool (*filter)(struct ConfItem *));
void add_conf_by_address(const char *, int, const char *, const char *, struct ConfItem *); void add_conf_by_address(const char *, int, const char *, const char *, struct ConfItem *);
void delete_one_address_conf(const char *, struct ConfItem *); void delete_one_address_conf(const char *, struct ConfItem *);
void clear_out_address_conf(enum aconf_category); void clear_out_address_conf(enum aconf_category);

View file

@ -478,13 +478,8 @@ find_dline(struct sockaddr *addr, int aftype)
return NULL; return NULL;
} }
/* void find_exact_conf_by_address(const char*, int, const char *)
* Input:
* Output: ConfItem if found
* Side-effects: None
*/
struct ConfItem * struct ConfItem *
find_exact_conf_by_address(const char *address, int type, const char *username) find_exact_conf_by_address_filtered(const char *address, int type, const char *username, bool (*filter)(struct ConfItem *))
{ {
int masktype, bits; int masktype, bits;
unsigned long hv; unsigned long hv;
@ -514,6 +509,9 @@ find_exact_conf_by_address(const char *address, int type, const char *username)
arec->masktype == masktype && arec->masktype == masktype &&
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username))) (arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
{ {
if (filter && !filter(arec->aconf))
continue;
if (masktype == HM_HOST) if (masktype == HM_HOST)
{ {
if (!irccmp(arec->Mask.hostname, address)) if (!irccmp(arec->Mask.hostname, address))
@ -530,6 +528,17 @@ find_exact_conf_by_address(const char *address, int type, const char *username)
return NULL; return NULL;
} }
/* void find_exact_conf_by_address(const char*, int, const char *)
* Input:
* Output: ConfItem if found
* Side-effects: None
*/
struct ConfItem *
find_exact_conf_by_address(const char *address, int type, const char *username)
{
return find_exact_conf_by_address_filtered(address, type, username, NULL);
}
/* void add_conf_by_address(const char*, int, const char *, /* void add_conf_by_address(const char*, int, const char *,
* struct ConfItem *aconf) * struct ConfItem *aconf)
* Input: * Input:

View file

@ -81,10 +81,23 @@ static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
static bool already_placed_kline(struct Client *, const char *, const char *, int); static bool 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 handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
static void remove_superseded_klines(const char *user, const char *host);
static void remove_permkline_match(struct Client *, struct ConfItem *); static void remove_permkline_match(struct Client *, struct ConfItem *);
static bool remove_temp_kline(struct Client *, struct ConfItem *); static bool remove_temp_kline(struct Client *, struct ConfItem *);
static void remove_prop_kline(struct Client *, struct ConfItem *); static void remove_prop_kline(struct Client *, struct ConfItem *);
static bool
is_local_kline(struct ConfItem *aconf)
{
return aconf->lifetime == 0;
}
static bool
is_temporary_kline(struct ConfItem *aconf)
{
return aconf->lifetime == 0 && (aconf->flags & CONF_FLAGS_TEMPORARY);
}
/* mo_kline() /* mo_kline()
* *
@ -209,6 +222,9 @@ mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
if(already_placed_kline(source_p, user, host, tkline_time)) if(already_placed_kline(source_p, user, host, tkline_time))
return; return;
if (!propagated)
remove_superseded_klines(user, host);
rb_set_time(); rb_set_time();
aconf = make_conf(); aconf = make_conf();
aconf->status = CONF_KILL; aconf->status = CONF_KILL;
@ -307,6 +323,8 @@ handle_remote_kline(struct Client *source_p, int tkline_time,
if(already_placed_kline(source_p, user, host, tkline_time)) if(already_placed_kline(source_p, user, host, tkline_time))
return; return;
remove_superseded_klines(user, host);
aconf = make_conf(); aconf = make_conf();
aconf->status = CONF_KILL; aconf->status = CONF_KILL;
@ -418,25 +436,30 @@ mo_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sour
cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN, cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
"%s %s", user, host); "%s %s", user, host);
if(aconf == NULL) bool removed_kline = false;
while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_local_kline), aconf != NULL)
{ {
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); removed_kline = true;
return;
if(remove_temp_kline(source_p, aconf))
continue;
remove_permkline_match(source_p, aconf);
} }
if(aconf->lifetime) aconf = find_exact_conf_by_address(host, CONF_KILL, user);
if (aconf)
{ {
if(propagated) if (propagated)
remove_prop_kline(source_p, aconf); remove_prop_kline(source_p, aconf);
else else
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
return;
} }
else if (!removed_kline)
if(remove_temp_kline(source_p, aconf)) {
return; sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
}
remove_permkline_match(source_p, aconf);
} }
/* ms_unkline() /* ms_unkline()
@ -475,23 +498,22 @@ static void
handle_remote_unkline(struct Client *source_p, const char *user, const char *host) handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
{ {
struct ConfItem *aconf; struct ConfItem *aconf;
bool removed_kline = false;
aconf = find_exact_conf_by_address(host, CONF_KILL, user); while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_local_kline), aconf != NULL)
if(aconf == NULL)
{ {
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host); removed_kline = true;
return;
if(remove_temp_kline(source_p, aconf))
continue;
remove_permkline_match(source_p, aconf);
} }
if(aconf->lifetime)
{ if (find_exact_conf_by_address(host, CONF_KILL, user))
sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host); sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
return; else if (!removed_kline)
} sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
if(remove_temp_kline(source_p, aconf))
return;
remove_permkline_match(source_p, aconf);
} }
/* apply_kline() /* apply_kline()
@ -734,21 +756,46 @@ already_placed_kline(struct Client *source_p, const char *luser, const char *lho
aconf = NULL; aconf = NULL;
} }
} }
if(aconf != NULL)
{
/* setting a tkline, or existing one is perm */
if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
{
reason = aconf->passwd ? aconf->passwd : "<No Reason>";
sendto_one_notice(source_p, if (aconf == NULL)
":[%s@%s] already K-Lined by [%s@%s] - %s", return false;
luser, lhost, aconf->user, aconf->host, reason);
return true; /* allow klines to be duplicated by longer ones */
if ((aconf->flags & CONF_FLAGS_TEMPORARY) &&
(tkline == 0 || tkline > aconf->hold - rb_current_time()))
return false;
reason = aconf->passwd ? aconf->passwd : "<No Reason>";
sendto_one_notice(source_p,
":[%s@%s] already K-Lined by [%s@%s] - %s",
luser, lhost, aconf->user, aconf->host, reason);
return true;
}
static void
remove_superseded_klines(const char *user, const char *host)
{
struct ConfItem *aconf;
while (aconf = find_exact_conf_by_address_filtered(host, CONF_KILL, user, is_temporary_kline), aconf != NULL)
{
rb_dlink_node *ptr;
int i;
for (i = 0; i < LAST_TEMP_TYPE; i++)
{
RB_DLINK_FOREACH(ptr, temp_klines[i].head)
{
if (aconf == ptr->data)
{
rb_dlinkDestroy(ptr, &temp_klines[i]);
delete_one_address_conf(aconf->host, aconf);
break;
}
}
} }
} }
return false;
} }
/* remove_permkline_match() /* remove_permkline_match()