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 *);
struct ConfItem *find_exact_conf_by_address(const char *address, int type,
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 delete_one_address_conf(const char *, struct ConfItem *);
void clear_out_address_conf(enum aconf_category);

View file

@ -478,13 +478,8 @@ find_dline(struct sockaddr *addr, int aftype)
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)
find_exact_conf_by_address_filtered(const char *address, int type, const char *username, bool (*filter)(struct ConfItem *))
{
int masktype, bits;
unsigned long hv;
@ -514,6 +509,9 @@ find_exact_conf_by_address(const char *address, int type, const char *username)
arec->masktype == masktype &&
(arec->username == NULL || username == NULL ? arec->username == username : !irccmp(arec->username, username)))
{
if (filter && !filter(arec->aconf))
continue;
if (masktype == HM_HOST)
{
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;
}
/* 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 *,
* struct ConfItem *aconf)
* 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 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 bool remove_temp_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()
*
@ -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))
return;
if (!propagated)
remove_superseded_klines(user, host);
rb_set_time();
aconf = make_conf();
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))
return;
remove_superseded_klines(user, host);
aconf = make_conf();
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,
"%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);
return;
removed_kline = true;
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);
else
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;
remove_permkline_match(source_p, aconf);
else if (!removed_kline)
{
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
}
}
/* ms_unkline()
@ -475,23 +498,22 @@ static void
handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
{
struct ConfItem *aconf;
bool removed_kline = false;
aconf = find_exact_conf_by_address(host, CONF_KILL, user);
if(aconf == NULL)
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);
return;
removed_kline = true;
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);
return;
}
if(remove_temp_kline(source_p, aconf))
return;
remove_permkline_match(source_p, aconf);
else if (!removed_kline)
sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
}
/* apply_kline()
@ -734,21 +756,46 @@ already_placed_kline(struct Client *source_p, const char *luser, const char *lho
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,
":[%s@%s] already K-Lined by [%s@%s] - %s",
luser, lhost, aconf->user, aconf->host, reason);
return true;
if (aconf == NULL)
return false;
/* 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()