From d0f23467c2bd1aa0d4ea333fef3b5e9c85fe53af Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 17 Jan 2025 23:08:37 +0100 Subject: [PATCH 1/5] Unique IP addresses for cloaked users --- common/struct_def.h | 4 +- ircd/channel.c | 2 +- ircd/list.c | 1 + ircd/s_conf.c | 120 +++++++++++++++++++++++++----------------- ircd/s_conf_ext.h | 2 +- ircd/s_misc.c | 17 +++--- ircd/s_misc_ext.h | 1 + ircd/s_sasl.c | 24 ++++++--- ircd/s_serv.c | 20 +++---- ircd/s_user.c | 2 +- support/config.h.dist | 6 +-- 11 files changed, 117 insertions(+), 82 deletions(-) diff --git a/common/struct_def.h b/common/struct_def.h index fddfbeee..6b3269f9 100644 --- a/common/struct_def.h +++ b/common/struct_def.h @@ -268,6 +268,7 @@ typedef enum Status { #endif #define IsCloaked(x) ((x)->user && (x)->user->flags & FLAGS_CLOAKED) #define SetCloaked(x) ((x)->user->flags |= FLAGS_CLOAKED) +#define HAS_CLOAK_IP(x) (!IN6_IS_ADDR_UNSPECIFIED(&((x)->cloak_ip))) #define IsTLS(x) ((x)->user && (x)->user->flags & FLAGS_TLS) #define SetTLS(x) ((x)->user->flags |= FLAGS_TLS) #define IsCAPNegotiation(x) (MyConnect(x) && (x)->cap_negotation) @@ -537,7 +538,7 @@ struct Client { char uid[UIDLEN+1]; u_int uidhashv; /* raw hash value of UID */ aClient *uhnext; - char *sasl_user; /* After successful login, the SASL user name will be stored here */ + char *sasl_user; /* After successful login, the SASL username will be stored here */ /* ** The following fields are allocated only for local clients ** (directly connected to *this* server with a socket. @@ -567,6 +568,7 @@ struct Client { char *auth; u_short port; /* and the remote port# too :-) */ struct IN_ADDR ip; /* keep real ip# too */ + struct IN_ADDR cloak_ip; /* cloak ip# */ struct hostent *hostp; char sockhost[HOSTLEN+1]; /* This is the host name from the socket ** and after which the connection was diff --git a/ircd/channel.c b/ircd/channel.c index cbc96dde..00ff8c86 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -389,7 +389,7 @@ static Link *match_modeid(int type, aClient *cptr, aChannel *chptr) } /* so now we check CIDR */ if (strchr(tmp->value.alist->host, '/') && - match_ipmask_client(tmp->value.alist->host, cptr, 0) == 0) + match_ipmask_client(tmp->value.alist->host, cptr, 0, 1) == 0) { break; } diff --git a/ircd/list.c b/ircd/list.c index 5e5f4928..4ea63e2b 100644 --- a/ircd/list.c +++ b/ircd/list.c @@ -147,6 +147,7 @@ aClient *make_client(aClient *from) cptr->caps = 0; cptr->sasl_service = NULL; cptr->cloak_tmp = NULL; + memset(&cptr->cloak_ip, 0, sizeof(cptr->cloak_ip)); } return (cptr); } diff --git a/ircd/s_conf.c b/ircd/s_conf.c index a695a3ae..81a0e6dd 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -450,11 +450,12 @@ void det_confs_butmask(aClient *cptr, int mask) * Now should work for IPv6 too. * returns -1 on error, 0 on match, 1 when NO match. */ -int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername) +int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername, int prefer_cloak) { int m; char *p; struct IN_ADDR addr; + struct IN_ADDR client_addr = prefer_cloak ? get_client_addr(cptr) : cptr->ip; char dummy[128]; char *omask; u_long lmask; @@ -500,15 +501,15 @@ int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername) j = m & 0x1F; /* number not mutliple of 32 bits */ m >>= 5; /* number of 32 bits */ - if (m && memcmp((void *)(addr.s6_addr), - (void *)(cptr->ip.s6_addr), m << 2)) + if (m && memcmp((void *)(addr.s6_addr), + (void *)(client_addr.s6_addr), m << 2)) return 1; if (j) { lmask = htonl((u_long)0xffffffffL << (32 - j)); if ((((u_int32_t *)(addr.s6_addr))[m] ^ - ((u_int32_t *)(cptr->ip.s6_addr))[m]) & lmask) + ((u_int32_t *)(client_addr.s6_addr))[m]) & lmask) return 1; } @@ -534,20 +535,51 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) int retval = -2; /* EXITC_NOILINE in register_user() */ /* We fill uaddr and uhost now, before aconf loop. */ - sprintf(uaddr, "%s@%s", cptr->username, sockhost); - if (hp) + if(HAS_CLOAK_IP(cptr) && cptr->cloak_tmp) { - char fullname[HOSTLEN+1]; + // Set IP address + char cloak_ip[HOSTLEN+1]; + inetntop(AF_INET6, (void *) cptr->cloak_ip.s6_addr, cloak_ip, sizeof(cloak_ip)); + if(cptr->user->sip) + { + MyFree(cptr->user->sip); + } + cptr->user->sip = mystrdup(cloak_ip); + + // Set hostname + strncpyzt(cptr->sockhost, cptr->cloak_tmp, HOSTLEN + 1); + strncpyzt(cptr->user->host, cptr->cloak_tmp, HOSTLEN + 1); + MyFree(cptr->cloak_tmp); + cptr->cloak_tmp = NULL; + + // Mark as cloaked + SetCloaked(cptr); - /* If not for add_local_domain, I wouldn't need this - ** fullname. Can't we add_local_domain somewhere in - ** dns code? --B. */ - strncpyzt(fullname, hp->h_name, sizeof(fullname)); - add_local_domain(fullname, HOSTLEN - strlen(fullname)); - Debug((DEBUG_DNS, "a_il: %s->%s", sockhost, fullname)); - sprintf(uhost, "%s@%s", cptr->username, fullname); + // Set variables for I-Line check + sprintf(uaddr, "%s@%s", cptr->username, cptr->user->sip); + sprintf(uhost, "%s@%s", cptr->username, cptr->user->host); + } + else + { + sprintf(uaddr, "%s@%s", cptr->username, sockhost); + if (hp) + { + char fullname[HOSTLEN + 1]; + + /* If not for add_local_domain, I wouldn't need this + ** fullname. Can't we add_local_domain somewhere in + ** dns code? --B. */ + strncpyzt(fullname, hp->h_name, sizeof(fullname)); + add_local_domain(fullname, HOSTLEN - strlen(fullname)); + Debug((DEBUG_DNS, "a_il: %s->%s", sockhost, fullname)); + sprintf(uhost, "%s@%s", cptr->username, fullname); + } + else + { + uaddr[0] = '\0'; + uhost[0] = '\0'; + } } - /* all uses of uhost are guarded by if (hp), so no need to zero it. */ for (aconf = conf; aconf; aconf = aconf->next) { @@ -585,7 +617,7 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) { int namematched = 0; - if (hp) + if (*uhost) { if (!UHConfMatch(aconf->name, uhost, ulen)) { @@ -625,7 +657,7 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) /* match_ipmask_client takes care of checking ** possible username if aconf->host has '@' */ - if (match_ipmask_client(aconf->host, cptr, 1)) + if (match_ipmask_client(aconf->host, cptr, 1, 1)) { /* Try another I:line. */ continue; @@ -661,7 +693,7 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) /* Various cases of +r. */ if (IsConfRestricted(aconf) || - (!hp && IsConfRNoDNS(aconf)) || + (!(*uhost) && IsConfRNoDNS(aconf)) || (!(cptr->flags & FLAGS_GOTID) && IsConfRNoIdent(aconf))) { SetRestricted(cptr); @@ -678,7 +710,7 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) #endif /* Copy uhost (hostname) over sockhost, if conf flag permits. */ - if (hp && !IsConfNoResolve(aconf)) + if (!IsCloaked(cptr) && *uhost && !IsConfNoResolve(aconf)) { get_sockhost(cptr, uhost+ulen); } @@ -687,15 +719,6 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) { find_bounce(cptr, ConfClass(aconf), -1); } - /* Set cloaked hostname */ - if(cptr->cloak_tmp && *cptr->cloak_tmp) - { - strncpyzt(cptr->sockhost, cptr->cloak_tmp, HOSTLEN + 1); - strncpyzt(cptr->user->host, cptr->cloak_tmp, HOSTLEN + 1); - MyFree(cptr->cloak_tmp); - cptr->cloak_tmp = NULL; - SetCloaked(cptr); - } break; } if (retval == -2) @@ -731,17 +754,18 @@ aConfItem *count_cnlines(Link *lp) static int add_cidr_limit(aClient *cptr, aConfItem *aconf) { patricia_node_t *pnode; + struct IN_ADDR addr = get_client_addr(cptr); if(aconf->class->cidr_amount == 0 || aconf->class->cidr_len == 0) return -1; - pnode = patricia_match_ip(ConfCidrTree(aconf), &cptr->ip); + pnode = patricia_match_ip(ConfCidrTree(aconf), &addr); - /* doesnt exist, create and then allow */ + /* doesn't exist, create and then allow */ if(pnode == NULL) { pnode = patricia_make_and_lookup_ip(ConfCidrTree(aconf), - &cptr->ip, + &addr, aconf->class->cidr_len); if(pnode == NULL) @@ -761,11 +785,12 @@ static int add_cidr_limit(aClient *cptr, aConfItem *aconf) static void remove_cidr_limit(aClient *cptr, aConfItem *aconf) { patricia_node_t *pnode; + struct IN_ADDR addr = get_client_addr(cptr); if(ConfMaxCidrAmount(aconf) == 0 || ConfCidrLen(aconf) == 0) return; - pnode = patricia_match_ip(ConfCidrTree(aconf), &cptr->ip); + pnode = patricia_match_ip(ConfCidrTree(aconf), &addr); if(pnode == NULL) return; @@ -940,16 +965,12 @@ int attach_conf(aClient *cptr, aConfItem *aconf) if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0 || ConfMaxHGlobal(aconf) > 0 || ConfMaxUHGlobal(aconf) > 0 ) { - if (IsSASLAuthed(cptr) && cptr->cloak_tmp != NULL) + if (IsCloaked(cptr)) { - /* - * Because all cloaked connections have the same IP address (CLOAK_IP), - * we use the cloaked hostname to check the Y-line limits (instead of IP or sockhost). - * (Originally from mh 2020-06-25) - */ - for ((user = hash_find_hostname(cptr->cloak_tmp, NULL)); user; user = user->hhnext) + // Check only by IP address because every SASL account has a unique IP address + for ((user = hash_find_ip(cptr->user->sip, NULL)); user; user = user->iphnext) { - if (!mycmp(cptr->cloak_tmp, user->host)) + if (!mycmp(cptr->user->sip, user->sip)) { int ret = attach_conf_check_limits(cptr, aconf, user, &hcnt, &ucnt, &ghcnt, &gucnt); if (ret != 0) @@ -1137,7 +1158,7 @@ aConfItem *find_Oline(char *name, aClient *cptr) */ if (match(tmp->host, userhost) && match(tmp->host, userip) && (!strchr(tmp->host, '/') - || match_ipmask_client(tmp->host, cptr, 1))) + || match_ipmask_client(tmp->host, cptr, 1, 1))) continue; if (tmp->clients < MaxLinks(Class(tmp))) return tmp; @@ -2229,6 +2250,7 @@ int find_kill(aClient *cptr, int timedklines, char **comment) #endif char *host, *ip, *name, *ident, *check; aConfItem *tmp; + struct IN_ADDR addr; #ifdef TKLINE int tklines = 1; #endif @@ -2242,8 +2264,8 @@ int find_kill(aClient *cptr, int timedklines, char **comment) } host = cptr->sockhost; - ip = (char *) inetntop(AF_INET6, (char *)&cptr->ip, ipv6string, - sizeof(ipv6string)); + addr = get_client_addr(cptr); + ip = (char *) inetntop(AF_INET6, &addr, ipv6string, sizeof(ipv6string)); if (!strcmp(host, ip)) ip = NULL; /* we don't have a name for the ip# */ name = cptr->user->username; @@ -2319,7 +2341,7 @@ int find_kill(aClient *cptr, int timedklines, char **comment) if (strchr(tmp->host, '/')) { if (match_ipmask_client((*tmp->host == '=') ? - tmp->host+1: tmp->host, cptr, 1)) + tmp->host+1: tmp->host, cptr, 1, 1)) continue; } else @@ -2332,7 +2354,7 @@ int find_kill(aClient *cptr, int timedklines, char **comment) else /* resolved */ if (strchr(tmp->host, '/')) { - if (match_ipmask_client(tmp->host, cptr, 1)) + if (match_ipmask_client(tmp->host, cptr, 1, 1)) continue; } else @@ -2555,7 +2577,7 @@ void find_bounce(aClient *cptr, int class, int fd) { if (strchr(aconf->host, '/')) { - if (match_ipmask_client(aconf->host, cptr, 1)) + if (match_ipmask_client(aconf->host, cptr, 1, 1)) continue; } else if (match(aconf->host, cptr->sockhost)) @@ -2773,7 +2795,7 @@ void do_kline(int tkline, char *who, time_t time, char *user, char *host, char * { if (match_ipmask_client(*aconf->host == '=' ? aconf->host + 1 : aconf->host, - acptr, 1)) + acptr, 1, 1)) { continue; } @@ -2798,7 +2820,7 @@ void do_kline(int tkline, char *who, time_t time, char *user, char *host, char * } if (strchr(aconf->host, '/')) { - if (match_ipmask_client(aconf->host, acptr, 1)) + if (match_ipmask_client(aconf->host, acptr, 1, 1)) { continue; } @@ -2903,7 +2925,7 @@ int prep_kline(int tkline, aClient *cptr, aClient *sptr, int parc, char **parv) /* disallow all forms of bad u@h format and block *@* without flags too */ err = 1; } - if (!err && host && strchr(host, '/') && match_ipmask_client(host, sptr, 0) == -1) + if (!err && host && strchr(host, '/') && match_ipmask_client(host, sptr, 0, 1) == -1) { /* check validity of 1.2.3.0/24 or it will be spewing errors ** for every connecting client. */ diff --git a/ircd/s_conf_ext.h b/ircd/s_conf_ext.h index d96f5714..95919406 100644 --- a/ircd/s_conf_ext.h +++ b/ircd/s_conf_ext.h @@ -39,7 +39,7 @@ extern char *networkname; #define EXTERN #endif /* S_CONF_C */ EXTERN void det_confs_butmask (aClient *cptr, int mask); -EXTERN int match_ipmask_client (char *mask, aClient *cptr, int maskwithusername); +EXTERN int match_ipmask_client (char *mask, aClient *cptr, int maskwithusername, int prefer_cloak); EXTERN int attach_Iline (aClient *cptr, Reg struct hostent *hp, char *sockhost); EXTERN aConfItem *count_cnlines (Reg Link *lp); diff --git a/ircd/s_misc.c b/ircd/s_misc.c index 36ba5d31..144b0a86 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -241,18 +241,19 @@ char *get_client_host(aClient *cptr) return nbuf; } +struct IN_ADDR get_client_addr(aClient *cptr) +{ + if(HAS_CLOAK_IP(cptr)) + return cptr->cloak_ip; + else + return cptr->ip; +} + char *get_client_ip(aClient *cptr) { if (cptr->user) { - if(IsCloaked(cptr)) - { - return CLOAK_IP; - } - else - { - return cptr->user->sip; - } + return cptr->user->sip; } else { diff --git a/ircd/s_misc_ext.h b/ircd/s_misc_ext.h index e957970f..f238cc53 100644 --- a/ircd/s_misc_ext.h +++ b/ircd/s_misc_ext.h @@ -42,6 +42,7 @@ EXTERN int check_registered (aClient *sptr); EXTERN int check_registered_service (aClient *sptr); EXTERN char *get_client_name (aClient *sptr, int showip); EXTERN char *get_client_host (aClient *cptr); +EXTERN struct IN_ADDR get_client_addr(aClient *cptr); EXTERN char *get_client_ip (aClient *cptr); EXTERN void get_sockhost (Reg aClient *cptr, Reg char *host); EXTERN char *my_name_for_link (char *name, Reg int count); diff --git a/ircd/s_sasl.c b/ircd/s_sasl.c index 907daa05..40e4608c 100644 --- a/ircd/s_sasl.c +++ b/ircd/s_sasl.c @@ -113,6 +113,7 @@ int m_sasl(aClient *cptr, aClient *sptr, int parc, char *parv[]) void m_sasl_service(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient * acptr; + char comment[BUFSIZE]; if (parc < 5) { @@ -147,22 +148,29 @@ void m_sasl_service(aClient *cptr, aClient *sptr, int parc, char *parv[]) else if (*parv[3] == 'L') { // Login - if (parc == 6) + if (parc == 7) { - if (bad_hostname(parv[5], strlen(parv[5]))) + // Validate and store the user's unique IP address + if (match_ipmask(SASL_CLOAK_IP_RANGE, parv[5]) + || inetpton(AF_INET6, parv[5], (void *) acptr->cloak_ip.s6_addr) != 1) { - char comment[BUFSIZE]; - sendto_flag(SCH_ERROR, "Received bad hostname %s from %s", parv[5], acptr->sasl_service->name); + sendto_flag(SCH_ERROR, "Received bad IP address %s from %s", parv[5], acptr->sasl_service->name); acptr->exitc = EXITC_SASL_REQUIRED; - snprintf(comment, BUFSIZE, "Bad hostname (%s)", parv[5]); + snprintf(comment, BUFSIZE, "Bad IP address (%s)", parv[5]); exit_client(acptr, acptr, &me, comment); return; } - else + if (bad_hostname(parv[6], strlen(parv[6]))) { - // Store cloaked hostname. It will finally be set by attach_Iline(). - acptr->cloak_tmp = mystrdup(parv[5]); + sendto_flag(SCH_ERROR, "Received bad hostname %s from %s", parv[6], acptr->sasl_service->name); + acptr->exitc = EXITC_SASL_REQUIRED; + snprintf(comment, BUFSIZE, "Bad hostname (%s)", parv[6]); + exit_client(acptr, acptr, &me, comment); + return; } + + // Store cloaked hostname. IP address and hostname will finally be set by attach_Iline(). + acptr->cloak_tmp = mystrdup(parv[6]); } acptr->sasl_user = mystrdup(parv[4]); sendto_one(acptr, replies[RPL_LOGGEDIN], me.name, BadTo(acptr->name), BadTo(acptr->name), diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 401e987c..e1ddb885 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -1837,6 +1837,7 @@ static void report_fd(aClient *sptr, aClient *acptr, char *to) { static char locip[100], *ret; int s; + struct IN_ADDR addr = get_client_addr(acptr); if (IsMe(acptr) || !acptr->acpt || !IsRegistered(acptr)) return; @@ -1844,16 +1845,15 @@ static void report_fd(aClient *sptr, aClient *acptr, char *to) s = strlen(ret) + 1; memcpy(locip, ret, s < sizeof(locip) ? s : sizeof(locip)); locip[sizeof(locip) - 1] = 0; - sendto_one(sptr,":%s %d %s %d %s %d %s %d %s %s %d", - ME,RPL_STATSLINKINFO,to, - acptr->fd, - locip, - acptr->acpt->port, - inetntop(AF_INET6, (char *)&acptr->ip, ipv6string, sizeof(ipv6string)), - acptr->port,acptr->name, - acptr->user ? acptr->user->username : acptr->auth, - acptr->user ? timeofday - acptr->user->last : -1 - ); + sendto_one(sptr, ":%s %d %s %d %s %d %s %d %s %s %d", + ME, RPL_STATSLINKINFO, to, + acptr->fd, + locip, + acptr->acpt->port, + inetntop(AF_INET6, &addr, ipv6string, sizeof(ipv6string)), + acptr->port, acptr->name, + acptr->user ? acptr->user->username : acptr->auth, + acptr->user ? timeofday - acptr->user->last : -1); } int m_stats(aClient *cptr, aClient *sptr, int parc, char *parv[]) diff --git a/ircd/s_user.c b/ircd/s_user.c index e9c5ec1b..d67ccca5 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -392,7 +392,7 @@ int register_user(aClient *cptr, aClient *sptr, char *nick, char *username) sptr->hostp->h_name : sptr->sockhost)) && match(xtmp->source_ip, sptr->user->sip) && strchr(xtmp->source_ip, '/') && - match_ipmask_client(xtmp->source_ip, sptr, 0))) + match_ipmask_client(xtmp->source_ip, sptr, 0, 1))) continue; SetXlined(sptr); break; diff --git a/support/config.h.dist b/support/config.h.dist index 41241f74..04ef2717 100644 --- a/support/config.h.dist +++ b/support/config.h.dist @@ -795,10 +795,10 @@ #define CLOAK_WHOISEXTRA "is a Cloaked Connection (Spoof)" /* - * The IP address shown instead of the real one - * (for example in /STATS L) for cloaked clients. (mandatory) + * Besides the cloaked hostname a user also gets a unique IP address assigned by a SASL service. + * This defines the range of IP addresses that are allowed to be set. */ -#define CLOAK_IP "255.255.255.255" +#define SASL_CLOAK_IP_RANGE "fdf0:584f:e66b::/48" /************************************************************************ * From 56ece57d84e04e3e666c46ef9b4a5d531d75eff2 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 18 Jan 2025 00:14:21 +0100 Subject: [PATCH 2/5] Unique IP addresses for cloaked users (clang-format) --- common/struct_def.h | 4 ++-- ircd/s_conf.c | 38 ++++++++++++++++++-------------------- ircd/s_conf_ext.h | 2 +- ircd/s_misc.c | 2 +- ircd/s_sasl.c | 3 +-- ircd/s_user.c | 9 ++++----- 6 files changed, 27 insertions(+), 31 deletions(-) diff --git a/common/struct_def.h b/common/struct_def.h index 6b3269f9..41d7c41e 100644 --- a/common/struct_def.h +++ b/common/struct_def.h @@ -268,7 +268,7 @@ typedef enum Status { #endif #define IsCloaked(x) ((x)->user && (x)->user->flags & FLAGS_CLOAKED) #define SetCloaked(x) ((x)->user->flags |= FLAGS_CLOAKED) -#define HAS_CLOAK_IP(x) (!IN6_IS_ADDR_UNSPECIFIED(&((x)->cloak_ip))) +#define HAS_CLOAK_IP(x) (!IN6_IS_ADDR_UNSPECIFIED(&((x)->cloak_ip))) #define IsTLS(x) ((x)->user && (x)->user->flags & FLAGS_TLS) #define SetTLS(x) ((x)->user->flags |= FLAGS_TLS) #define IsCAPNegotiation(x) (MyConnect(x) && (x)->cap_negotation) @@ -568,7 +568,7 @@ struct Client { char *auth; u_short port; /* and the remote port# too :-) */ struct IN_ADDR ip; /* keep real ip# too */ - struct IN_ADDR cloak_ip; /* cloak ip# */ + struct IN_ADDR cloak_ip; /* cloak ip# */ struct hostent *hostp; char sockhost[HOSTLEN+1]; /* This is the host name from the socket ** and after which the connection was diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 81a0e6dd..b23f79e2 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -455,7 +455,7 @@ int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername, int pre int m; char *p; struct IN_ADDR addr; - struct IN_ADDR client_addr = prefer_cloak ? get_client_addr(cptr) : cptr->ip; + struct IN_ADDR client_addr = prefer_cloak ? get_client_addr(cptr) : cptr->ip; char dummy[128]; char *omask; u_long lmask; @@ -501,15 +501,16 @@ int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername, int pre j = m & 0x1F; /* number not mutliple of 32 bits */ m >>= 5; /* number of 32 bits */ - if (m && memcmp((void *)(addr.s6_addr), - (void *)(client_addr.s6_addr), m << 2)) + if (m && memcmp((void *) (addr.s6_addr), + (void *) (client_addr.s6_addr), m << 2)) return 1; if (j) { - lmask = htonl((u_long)0xffffffffL << (32 - j)); - if ((((u_int32_t *)(addr.s6_addr))[m] ^ - ((u_int32_t *)(client_addr.s6_addr))[m]) & lmask) + lmask = htonl((u_long) 0xffffffffL << (32 - j)); + if ((((u_int32_t *) (addr.s6_addr))[m] ^ + ((u_int32_t *) (client_addr.s6_addr))[m]) & + lmask) return 1; } @@ -535,12 +536,12 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) int retval = -2; /* EXITC_NOILINE in register_user() */ /* We fill uaddr and uhost now, before aconf loop. */ - if(HAS_CLOAK_IP(cptr) && cptr->cloak_tmp) + if (HAS_CLOAK_IP(cptr) && cptr->cloak_tmp) { // Set IP address - char cloak_ip[HOSTLEN+1]; + char cloak_ip[HOSTLEN + 1]; inetntop(AF_INET6, (void *) cptr->cloak_ip.s6_addr, cloak_ip, sizeof(cloak_ip)); - if(cptr->user->sip) + if (cptr->user->sip) { MyFree(cptr->user->sip); } @@ -765,8 +766,8 @@ static int add_cidr_limit(aClient *cptr, aConfItem *aconf) if(pnode == NULL) { pnode = patricia_make_and_lookup_ip(ConfCidrTree(aconf), - &addr, - aconf->class->cidr_len); + &addr, + aconf->class->cidr_len); if(pnode == NULL) return -1; @@ -1157,8 +1158,7 @@ aConfItem *find_Oline(char *name, aClient *cptr) ** the ip does. */ if (match(tmp->host, userhost) && match(tmp->host, userip) && - (!strchr(tmp->host, '/') - || match_ipmask_client(tmp->host, cptr, 1, 1))) + (!strchr(tmp->host, '/') || match_ipmask_client(tmp->host, cptr, 1, 1))) continue; if (tmp->clients < MaxLinks(Class(tmp))) return tmp; @@ -2340,8 +2340,7 @@ int find_kill(aClient *cptr, int timedklines, char **comment) { if (strchr(tmp->host, '/')) { - if (match_ipmask_client((*tmp->host == '=') ? - tmp->host+1: tmp->host, cptr, 1, 1)) + if (match_ipmask_client((*tmp->host == '=') ? tmp->host + 1 : tmp->host, cptr, 1, 1)) continue; } else @@ -2353,10 +2352,10 @@ int find_kill(aClient *cptr, int timedklines, char **comment) continue; else /* resolved */ if (strchr(tmp->host, '/')) - { + { if (match_ipmask_client(tmp->host, cptr, 1, 1)) continue; - } + } else if (match(tmp->host, ip) && match(tmp->host, host)) @@ -2793,9 +2792,8 @@ void do_kline(int tkline, char *who, time_t time, char *user, char *host, char * /* unresolved */ if (strchr(aconf->host, '/')) { - if (match_ipmask_client(*aconf->host == '=' ? - aconf->host + 1 : aconf->host, - acptr, 1, 1)) + if (match_ipmask_client(*aconf->host == '=' ? aconf->host + 1 : aconf->host, + acptr, 1, 1)) { continue; } diff --git a/ircd/s_conf_ext.h b/ircd/s_conf_ext.h index 95919406..01554513 100644 --- a/ircd/s_conf_ext.h +++ b/ircd/s_conf_ext.h @@ -39,7 +39,7 @@ extern char *networkname; #define EXTERN #endif /* S_CONF_C */ EXTERN void det_confs_butmask (aClient *cptr, int mask); -EXTERN int match_ipmask_client (char *mask, aClient *cptr, int maskwithusername, int prefer_cloak); +EXTERN int match_ipmask_client(char *mask, aClient *cptr, int maskwithusername, int prefer_cloak); EXTERN int attach_Iline (aClient *cptr, Reg struct hostent *hp, char *sockhost); EXTERN aConfItem *count_cnlines (Reg Link *lp); diff --git a/ircd/s_misc.c b/ircd/s_misc.c index 144b0a86..4ce256a9 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -243,7 +243,7 @@ char *get_client_host(aClient *cptr) struct IN_ADDR get_client_addr(aClient *cptr) { - if(HAS_CLOAK_IP(cptr)) + if (HAS_CLOAK_IP(cptr)) return cptr->cloak_ip; else return cptr->ip; diff --git a/ircd/s_sasl.c b/ircd/s_sasl.c index 40e4608c..c4665fa1 100644 --- a/ircd/s_sasl.c +++ b/ircd/s_sasl.c @@ -151,8 +151,7 @@ void m_sasl_service(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (parc == 7) { // Validate and store the user's unique IP address - if (match_ipmask(SASL_CLOAK_IP_RANGE, parv[5]) - || inetpton(AF_INET6, parv[5], (void *) acptr->cloak_ip.s6_addr) != 1) + if (match_ipmask(SASL_CLOAK_IP_RANGE, parv[5]) || inetpton(AF_INET6, parv[5], (void *) acptr->cloak_ip.s6_addr) != 1) { sendto_flag(SCH_ERROR, "Received bad IP address %s from %s", parv[5], acptr->sasl_service->name); acptr->exitc = EXITC_SASL_REQUIRED; diff --git a/ircd/s_user.c b/ircd/s_user.c index 80be8268..e1864dc2 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -388,11 +388,10 @@ int register_user(aClient *cptr, aClient *sptr, char *nick, char *username) match(xtmp->name3, nick)) continue; if (!BadPtr(xtmp->source_ip) && - (match(xtmp->source_ip, (sptr->hostp ? - sptr->hostp->h_name : sptr->sockhost)) && - match(xtmp->source_ip, sptr->user->sip) && - strchr(xtmp->source_ip, '/') && - match_ipmask_client(xtmp->source_ip, sptr, 0, 1))) + (match(xtmp->source_ip, (sptr->hostp ? sptr->hostp->h_name : sptr->sockhost)) && + match(xtmp->source_ip, sptr->user->sip) && + strchr(xtmp->source_ip, '/') && + match_ipmask_client(xtmp->source_ip, sptr, 0, 1))) continue; SetXlined(sptr); break; From 2a3ab0c19531d7c6809f4e80d75f11b7f4dd222b Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 18 Jan 2025 00:17:15 +0100 Subject: [PATCH 3/5] Unique IP addresses for cloaked users (clang-format) --- ircd/s_conf.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ircd/s_conf.c b/ircd/s_conf.c index b23f79e2..cf4ece95 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -2337,17 +2337,15 @@ int find_kill(aClient *cptr, int timedklines, char **comment) check = ident; /* host & IP matching.. */ if (!ip) /* unresolved */ - { + { if (strchr(tmp->host, '/')) - { + { if (match_ipmask_client((*tmp->host == '=') ? tmp->host + 1 : tmp->host, cptr, 1, 1)) continue; - } - else - if (match((*tmp->host == '=') ? tmp->host+1 : - tmp->host, host)) - continue; - } + } + else if (match((*tmp->host == '=') ? tmp->host + 1 : tmp->host, host)) + continue; + } else if (*tmp->host == '=') /* numeric only */ continue; else /* resolved */ From f89557a903c0cacea2df841883f880f3991f654c Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 18 Jan 2025 10:02:26 +0100 Subject: [PATCH 4/5] Updated sasl.md --- doc/sasl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/sasl.md b/doc/sasl.md index a170a397..19f71f8f 100644 --- a/doc/sasl.md +++ b/doc/sasl.md @@ -4,7 +4,7 @@ This implementation is based on the documentation from Mantas Mikulėnas. Read * The following things are different: * logout is not supported * abortion of authentication is not supported, the user has to disable SASL explicitly at his IRC client if he wants to connect without authentication -* the L-message contains the cloak (`L :`) and the ircd sets it after successful authentication +* if the user has configured a cloaked hostname, the L-message contains a unique local IPv6 address and the cloaked hostname (`L [ :]`) * the H-message contains a hostmask (`H [[ident]@ip]`) * additional N-message to allow the SASL service to send a NOTICE to a user (`N :`) * additional K-message to allow the SASL service to disconnect a user before registration (K :`), e.g. if he fails to log in too often @@ -38,7 +38,7 @@ You need to set up at least one service with the flags SERVICE_WANT_SASL and SER // The server forwards the message to the SASL service [Server -> Service] :000B SASL 000BAAAAD SASLService@irc1.localhost C dXNlcjEAdXNlcjEAdXNlcjEtcGFzc3dvcmQxMjM= // The service validates the credentials and sends success messages including the cloaked hostname - [Service -> Server] ENCAP 000B SASL 000BAAAAD * L user1 :spoof1.ircnet.com + [Service -> Server] ENCAP 000B SASL 000BAAAAD * L user1 fdf0:584f:e66b:1::1 :spoof1.ircnet.com [Service -> Server] ENCAP 000B SASL 000BAAAAD * D S // The server sets the cloaked hostname and sends a success message to the client [Server -> User] :irc1.localhost 900 patrick :You are now logged in as user1. From fbedeb1186c745199ced360fa2a85470ad210c0a Mon Sep 17 00:00:00 2001 From: Patrick Date: Fri, 24 Jan 2025 23:44:11 +0100 Subject: [PATCH 5/5] Unique IP addresses for cloaked users - bugfix in I-Line check --- ircd/s_conf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ircd/s_conf.c b/ircd/s_conf.c index cf4ece95..a6cc33c4 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -577,7 +577,6 @@ int attach_Iline(aClient *cptr, struct hostent *hp, char *sockhost) } else { - uaddr[0] = '\0'; uhost[0] = '\0'; } }