From f53d2f45de5f9bde3eb7b62c7e31995c6e91ef14 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Wed, 15 Apr 2020 23:51:39 +0100 Subject: [PATCH 1/4] Refactor check_one_kline a tiny bit --- ircd/client.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/ircd/client.c b/ircd/client.c index a19c664f..20ae47f3 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -580,9 +580,16 @@ check_one_kline(struct ConfItem *kline) struct Client *client_p; rb_dlink_node *ptr; rb_dlink_node *next_ptr; + int masktype; + int bits; + struct rb_sockaddr_storage sockaddr; + + masktype = parse_netmask(kline->host, (struct sockaddr_storage *)&sockaddr, &bits); RB_DLINK_FOREACH_SAFE(ptr, next_ptr, lclient_list.head) { + int matched = 0; + client_p = ptr->data; if(IsMe(client_p) || !IsPerson(client_p)) @@ -592,29 +599,20 @@ check_one_kline(struct ConfItem *kline) continue; /* match one kline */ - { - int matched = 0; - int masktype; - int bits; - struct rb_sockaddr_storage sockaddr; - - masktype = parse_netmask(kline->host, (struct sockaddr_storage *)&sockaddr, &bits); - - switch (masktype) { - case HM_IPV4: - case HM_IPV6: - if(comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, - (struct sockaddr *)&sockaddr, bits)) - matched = 1; - case HM_HOST: - if (match(kline->host, client_p->orighost)) - matched = 1; - } - - if (!matched) - continue; + switch (masktype) { + case HM_IPV4: + case HM_IPV6: + if (comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, + (struct sockaddr *)&sockaddr, bits)) + matched = 1; + case HM_HOST: + if (match(kline->host, client_p->orighost)) + matched = 1; } + if (!matched) + continue; + if(IsExemptKline(client_p)) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, From de0673d7ad78573a052ea4ae0a38fd8b161b5bc4 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sat, 18 Apr 2020 16:57:22 +0100 Subject: [PATCH 2/4] Move ipv4-in-ipv6 handling to find_conf_by_address This removes some inconsistencies: first of all it applies to both CONF_KILL searches by IP in find_address_conf, and secondly it applies to find_kline, which would have been an edge case before. --- ircd/hostmask.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/ircd/hostmask.c b/ircd/hostmask.c index a5ca670a..580a3509 100644 --- a/ircd/hostmask.c +++ b/ircd/hostmask.c @@ -216,6 +216,8 @@ find_conf_by_address(const char *name, const char *sockhost, unsigned long hprecv = 0; struct ConfItem *hprec = NULL; struct AddressRec *arec; + struct sockaddr_in ip4; + struct sockaddr *pip4 = NULL; int b; if(username == NULL) @@ -223,9 +225,13 @@ find_conf_by_address(const char *name, const char *sockhost, if(addr) { - /* Check for IPV6 matches... */ - if(fam == AF_INET6) + if (fam == AF_INET) + pip4 = addr; + + if (fam == AF_INET6) { + if (type == CONF_KILL && rb_ipv4_from_ipv6((struct sockaddr_in6 *)addr, &ip4)) + pip4 = (struct sockaddr *)&ip4; for (b = 128; b >= 0; b -= 16) { @@ -244,15 +250,15 @@ find_conf_by_address(const char *name, const char *sockhost, } } } - else - if(fam == AF_INET) + + if (pip4 != NULL) { for (b = 32; b >= 0; b -= 8) { - for (arec = atable[hash_ipv4(addr, b)]; arec; arec = arec->next) + for (arec = atable[hash_ipv4(pip4, b)]; arec; arec = arec->next) if(arec->type == (type & ~0x1) && arec->masktype == HM_IPV4 && - comp_with_mask_sock(addr, (struct sockaddr *)&arec->Mask.ipa.addr, + comp_with_mask_sock(pip4, (struct sockaddr *)&arec->Mask.ipa.addr, arec->Mask.ipa.bits) && (type & 0x1 || match(arec->username, username)) && (type != CONF_CLIENT || !arec->auth_user || @@ -364,7 +370,6 @@ find_address_conf(const char *host, const char *sockhost, const char *user, { struct ConfItem *iconf, *kconf; const char *vuser; - struct sockaddr_in ip4; /* Find the best I-line... If none, return NULL -A1kmm */ if(!(iconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_CLIENT, aftype, user, auth_user))) @@ -415,14 +420,6 @@ find_address_conf(const char *host, const char *sockhost, const char *user, return kconf; } - if(ip != NULL && ip->sa_family == AF_INET6 && - rb_ipv4_from_ipv6((const struct sockaddr_in6 *)(const void *)ip, &ip4)) - { - kconf = find_conf_by_address(NULL, NULL, NULL, (struct sockaddr *)&ip4, CONF_KILL, AF_INET, vuser, NULL); - if(kconf) - return kconf; - } - return iconf; } From 9274c0f3f4a23751d68355f801fbf5d4d64121e8 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sun, 19 Apr 2020 00:53:10 +0100 Subject: [PATCH 3/4] Align check_one_kline better with find_kline --- ircd/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ircd/client.c b/ircd/client.c index 20ae47f3..072d0a4c 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -605,9 +605,13 @@ check_one_kline(struct ConfItem *kline) if (comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, (struct sockaddr *)&sockaddr, bits)) matched = 1; + break; case HM_HOST: if (match(kline->host, client_p->orighost)) matched = 1; + if (match(kline->host, client_p->sockhost)) + matched = 1; + break; } if (!matched) From 485d245ec0f48cff273377bc5babacd8641a2668 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sun, 19 Apr 2020 02:16:17 +0100 Subject: [PATCH 4/4] Add ipv4-in-ipv6 logic to check_one_kline --- ircd/client.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ircd/client.c b/ircd/client.c index 072d0a4c..9cc059f8 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -583,6 +583,7 @@ check_one_kline(struct ConfItem *kline) int masktype; int bits; struct rb_sockaddr_storage sockaddr; + struct sockaddr_in ip4; masktype = parse_netmask(kline->host, (struct sockaddr_storage *)&sockaddr, &bits); @@ -601,9 +602,15 @@ check_one_kline(struct ConfItem *kline) /* match one kline */ switch (masktype) { case HM_IPV4: + if (client_p->localClient->ip.ss_family == AF_INET6 && + rb_ipv4_from_ipv6((struct sockaddr_in6 *)&client_p->localClient->ip, &ip4) + && comp_with_mask_sock((struct sockaddr *)&ip4, (struct sockaddr *)&sockaddr, bits)) + matched = 1; + /* fallthrough */ case HM_IPV6: - if (comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, - (struct sockaddr *)&sockaddr, bits)) + if (client_p->localClient->ip.ss_family == sockaddr.ss_family && + comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, + (struct sockaddr *)&sockaddr, bits)) matched = 1; break; case HM_HOST: