X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/e340eee89a1d28e809877483cfe90ebb6c764597..9172b03e94b4a23862c5ffeab84d2bcec001cb64:/channel/channelbans.c diff --git a/channel/channelbans.c b/channel/channelbans.c index 8c3255c7..fc86bc76 100644 --- a/channel/channelbans.c +++ b/channel/channelbans.c @@ -9,34 +9,41 @@ #include "../lib/irc_string.h" #include "../irc/irc_config.h" #include "../irc/irc.h" +#include "../lib/irc_ipv6.h" /* * nickmatchban: * Returns true iff the supplied nick* matches the supplied ban* + * + * "visibleonly" flag indicates that we shouldn't check against the real + * host if it's masked. */ -int nickmatchban(nick *np, chanban *bp) { - const char *ipstring; +int nickmatchban(nick *np, chanban *bp, int visibleonly) { char fakehost[HOSTLEN+1]; + char *ident; - /* nick/ident section: return 0 (no match) if they don't match */ - + /* 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 */ + + /* 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(np->ident,bp->user->content) && - (!IsSetHost(np) || !np->shident || - ircd_strcmp(np->shident->content,bp->user->content))) + 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,np->ident) && - (!IsSetHost(np) || !np->shident || - !match2strings(bp->user->content, np->shident->content))) + !match2strings(bp->user->content,ident)) return 0; if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick)) @@ -48,95 +55,72 @@ int nickmatchban(nick *np, chanban *bp) { if (bp->flags & CHANBAN_HOSTANY) return 1; + + /* "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_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) + 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) { - if (bp->flags & CHANBAN_HOSTEXACT) { - /* If it's an exact IP ban we can compare it numerically */ - 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; + /* 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. */ - /* 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 { - /* It's not an exact IP ban so let's generate the string */ - ipstring=IPtostr(np->p_ipaddr); - - if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,ipstring)) - 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 (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 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_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; } /* * nickbanned: * Returns true iff the supplied nick* is banned on the supplied chan* + * + * Pass the visibleonly flag on to nickbanned(). */ - -int nickbanned(nick *np, channel *cp) { +int nickbanned(nick *np, channel *cp, int visibleonly) { chanban *cbp; for (cbp=cp->bans;cbp;cbp=cbp->next) { - if (nickmatchban(np,cbp)) + if (nickmatchban(np,cbp,visibleonly)) return 1; }