X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/050371e895921db84e67d86d9948c0ff221436db..fc03eb2dd7092582030b2694d69174ce2bfb82dd:/channel/channelbans.c diff --git a/channel/channelbans.c b/channel/channelbans.c index 3fd55215..fc86bc76 100644 --- a/channel/channelbans.c +++ b/channel/channelbans.c @@ -9,43 +9,45 @@ #include "../lib/irc_string.h" #include "../irc/irc_config.h" #include "../irc/irc.h" +#include "../lib/irc_ipv6.h" /* - * nickmatchban_visible: + * nickmatchban: * Returns true iff the supplied nick* matches the supplied ban* - * Doesn't check "invisible" things like true hosts and IPs for - * +x/+h users. * - * copy & pasted this, touch and go whether this was a good idea. + * "visibleonly" flag indicates that we shouldn't check against the real + * host if it's masked. */ -int nickmatchban_visible(nick *np, chanban *bp) { +int nickmatchban(nick *np, chanban *bp, int visibleonly) { char fakehost[HOSTLEN+1]; - char *visibleident; + char *ident; - /* Don't waste time on invalid bans */ + /* If it's not valid, don't bother */ if (bp->flags & CHANBAN_INVALID) return 0; /* nick/ident section: return 0 (no match) if they don't match */ - /* Determine the visible ident for sethost users. Don't test the real one. */ - if (IsSetHost(np) && np->shident && *np->shident->content) - visibleident=np->shident->content; - else - visibleident=np->ident; + /* Pick up the visible username. If a sethost username is set, the real + * username is not checked. */ + ident=np->ident; + if (IsSetHost(np) && np->shident) + ident=np->shident->content; - if (bp->flags & CHANBAN_USEREXACT && ircd_strcmp(visibleident,bp->user->content)) + if (bp->flags & CHANBAN_USEREXACT && + ircd_strcmp(ident,bp->user->content)) return 0; if (bp->flags & CHANBAN_NICKEXACT && ircd_strcmp(np->nick,bp->nick->content)) return 0; - if (bp->flags & CHANBAN_USERMASK && !match2strings(bp->user->content,visibleident)) + if (bp->flags & CHANBAN_USERMASK && + !match2strings(bp->user->content,ident)) return 0; if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick)) - return 0; + return 0; /* host section. Return 1 (match) if they do match * Note that if user or ident was specified, they've already been checked @@ -53,197 +55,57 @@ int nickmatchban_visible(nick *np, chanban *bp) { if (bp->flags & CHANBAN_HOSTANY) return 1; - - if ((bp->flags & CHANBAN_CIDR) && (bp->flags & CHANBAN_HOSTEXACT)) { - unsigned int cip; - unsigned char *ch; - - /* CIDR bans don't visibly match sethosted users */ - if (IsSetHost(np) || (IsAccount(np) && IsHideHost(np))) - return 0; - - /* CIDR bans don't match IPv6 hosts */ - if (!irc_in_addr_is_ipv4(&(np->p_ipaddr))) - return 0; - - /* Extract the client's IP address into a usable format */ - ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]); - cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]); - if ((cip & bp->mask) == bp->ipaddr) + /* "visibleonly" means don't check IP/realhost if they are sethosted/+x. + * We change this to mean "Don't check IP/realhost unconditionally" - by + * clearing it to 0 if the user isn't sethosted or +x. Simplifies logic + * later. */ + + if (!(IsSetHost(np) || (IsAccount(np) && IsHideHost(np)))) + visibleonly=0; + + if ((bp->flags & CHANBAN_IP) && !visibleonly) { + if (ipmask_check(&(np->ipnode->prefix->sin), &(bp->ipaddr), bp->prefixlen)) return 1; - - return 0; /* A CIDR ban won't match any other way */ } - if (bp->flags & CHANBAN_IP) { - /* IP bans don't match sethosted users */ - if (IsSetHost(np) || (IsAccount(np) && IsHideHost(np))) - return 0; - - if (bp->flags & CHANBAN_HOSTEXACT) { - /* Only exact IP bans are valid */ - unsigned int cip; - unsigned char *ch; - - /* Well, it won't match if it's not an IPv4 host */ - if (!irc_in_addr_is_ipv4(&(np->p_ipaddr))) - return 0; - - /* Extract the client's IP address into a usable format */ - ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]); - cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]); + /* Hostname bans need to be checked against +x host, +h host (if set) + * and actual host. Note that the +x host is only generated (and checked) if it's + * possible for the ban to match a hidden host. And it's checked regardless + * of whether the user is actually +x. */ - if (cip==bp->ipaddr) - return 1; - } - } else { - /* Hostname bans need to be checked against +x host, +h host (if set) - * and actual host. Note that the +x host is only generated (and checked) if it's - * possible for the ban to match a hidden host.. */ + if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) { + sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST); + + if ((bp->flags & CHANBAN_HOSTEXACT) && + !ircd_strcmp(fakehost, bp->host->content)) + return 1; - if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) { - sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST); - - if ((bp->flags & CHANBAN_HOSTEXACT) && - !ircd_strcmp(fakehost, bp->host->content)) - return 1; - - if ((bp->flags & CHANBAN_HOSTMASK) && - match2strings(bp->host->content, fakehost)) - return 1; - } + if ((bp->flags & CHANBAN_HOSTMASK) && + match2strings(bp->host->content, fakehost)) + return 1; + } - if (IsSetHost(np)) { - if ((bp->flags & CHANBAN_HOSTEXACT) && + if (IsSetHost(np)) { + if ((bp->flags & CHANBAN_HOSTEXACT) && !ircd_strcmp(np->sethost->content, bp->host->content)) - return 1; + return 1; - if ((bp->flags & CHANBAN_HOSTMASK) && + if ((bp->flags & CHANBAN_HOSTMASK) && match2strings(bp->host->content, np->sethost->content)) - return 1; - } - - /* If the user is +h or +rx don't check their real host */ - if (IsSetHost(np) || (IsHideHost(np) && IsAccount(np))) - return 0; - - if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content)) - return 1; - - if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content)) return 1; } - return 0; -} - -/* - * nickmatchban: - * Returns true iff the supplied nick* matches the supplied ban* - */ - -int nickmatchban(nick *np, chanban *bp) { - char fakehost[HOSTLEN+1]; - - /* nick/ident section: return 0 (no match) if they don't match */ - - if (bp->flags & CHANBAN_INVALID) - return 0; - - if (bp->flags & CHANBAN_USEREXACT && - ircd_strcmp(np->ident,bp->user->content) && - (!IsSetHost(np) || !np->shident || - ircd_strcmp(np->shident->content,bp->user->content))) - return 0; - - if (bp->flags & CHANBAN_NICKEXACT && ircd_strcmp(np->nick,bp->nick->content)) - return 0; - - if (bp->flags & CHANBAN_USERMASK && - !match2strings(bp->user->content,np->ident) && - (!IsSetHost(np) || !np->shident || - !match2strings(bp->user->content, np->shident->content))) + /* If we are only checking visible host and the host is somehow masked, don't check + * against the real one. */ + if (visibleonly) return 0; - if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick)) - return 0; - - /* host section. Return 1 (match) if they do match - * Note that if user or ident was specified, they've already been checked - */ - - if (bp->flags & CHANBAN_HOSTANY) + if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content)) return 1; - - if ((bp->flags & CHANBAN_CIDR) && (bp->flags & CHANBAN_HOSTEXACT)) { - unsigned int cip; - unsigned char *ch; - - /* CIDR bans don't match IPv6 hosts */ - if (!irc_in_addr_is_ipv4(&(np->p_ipaddr))) - return 0; - - /* Extract the client's IP address into a usable format */ - ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]); - cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]); - - if ((cip & bp->mask) == bp->ipaddr) - return 1; - - return 0; /* A CIDR ban won't match any other way */ - } - if (bp->flags & CHANBAN_IP) { - if (bp->flags & CHANBAN_HOSTEXACT) { - /* Only exact matches for IP bans */ - unsigned int cip; - unsigned char *ch; - - /* Well, it won't match if it's not an IPv4 host */ - if (!irc_in_addr_is_ipv4(&(np->p_ipaddr))) - return 0; - - /* Extract the client's IP address into a usable format */ - ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]); - cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]); - - if (cip==bp->ipaddr) - return 1; - } - } else { - /* Hostname bans need to be checked against +x host, +h host (if set) - * and actual host. Note that the +x host is only generated (and checked) if it's - * possible for the ban to match a hidden host.. */ - - if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) { - sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST); - - if ((bp->flags & CHANBAN_HOSTEXACT) && - !ircd_strcmp(fakehost, bp->host->content)) - return 1; - - if ((bp->flags & CHANBAN_HOSTMASK) && - match2strings(bp->host->content, fakehost)) - return 1; - } - - if (IsSetHost(np)) { - if ((bp->flags & CHANBAN_HOSTEXACT) && - !ircd_strcmp(np->sethost->content, bp->host->content)) - return 1; - - if ((bp->flags & CHANBAN_HOSTMASK) && - match2strings(bp->host->content, np->sethost->content)) - return 1; - } - - if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content)) - return 1; - - if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content)) - return 1; - } + if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content)) + return 1; return 0; } @@ -252,27 +114,18 @@ int nickmatchban(nick *np, chanban *bp) { * nickbanned: * Returns true iff the supplied nick* is banned on the supplied chan* * - * Also nickbanned_visible - doesn't violate privacy by checking hidden - * hosts and idents. Factored into one function to reduce copy&paste. + * Pass the visibleonly flag on to nickbanned(). */ -static int nickbanned_real(nick *np, channel *cp, int (*cmpfunc)(nick *, chanban *)) { +int nickbanned(nick *np, channel *cp, int visibleonly) { chanban *cbp; for (cbp=cp->bans;cbp;cbp=cbp->next) { - if (cmpfunc(np,cbp)) + if (nickmatchban(np,cbp,visibleonly)) return 1; } return 0; } - -int nickbanned(nick *np, channel *cp) { - return nickbanned_real(np,cp,nickmatchban); -} - -int nickbanned_visible(nick *np, channel *cp) { - return nickbanned_real(np,cp,nickmatchban_visible); -} /* * setban: