]> jfr.im git - irc/quakenet/newserv.git/blobdiff - channel/channelbans.c
Merge pull request #1 from meeb/meeb
[irc/quakenet/newserv.git] / channel / channelbans.c
index 57af8bbf17a3c53098ebb89f0fb435253214e1ef..fc86bc760fafe50a2b7e210c1717a53a9419bf48 100644 (file)
@@ -9,44 +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) {
-  const char *ipstring;
+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
@@ -54,210 +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) {
-      /* 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;
-
-      /* 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 {
-      /* 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 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) {
-  const char *ipstring;
-  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) {
-      /* 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;
-
-      /* 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_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;
 }
@@ -266,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: