Bläddra i källkod

* Added primitive CIDR ban support (enforcebans/kickban/getop).

svn: 1722
Bryan Drewery 21 år sedan
förälder
incheckning
d08a62f16b
7 ändrade filer med 96 tillägg och 7 borttagningar
  1. 1 0
      doc/UPDATES
  2. 80 0
      src/match.c
  3. 2 0
      src/match.h
  4. 2 1
      src/mod/irc.mod/chan.c
  5. 6 5
      src/mod/irc.mod/irc.c
  6. 1 1
      src/mod/irc.mod/mode.c
  7. 4 0
      src/socket.h

+ 1 - 0
doc/UPDATES

@@ -59,6 +59,7 @@ Lines prefixxed with '-' were disabled before release and are not finishsed.
 * Changed HIJACK warning to suggest that it may just be a box reboot.
 * Now using OpenBSD's strlcpy()
 * Added a (temporarily) static auto-op delay of 6 seconds.
+* Added primitive CIDR ban support (enforcebans/kickban/getop).
 
 1.2
 * No longer displaying SALTS on ./bin -v

+ 80 - 0
src/match.c

@@ -24,6 +24,7 @@
 #include "common.h"
 #include "match.h"
 #include "rfc1459.h"
+#include "socket.h"
 
 #define QUOTE '\\' /* quoting character (overrides wildcards) */
 #define WILDS '*'  /* matches 0 or more characters (including spaces) */
@@ -196,3 +197,82 @@ int _wild_match(register unsigned char *m, register unsigned char *n)
     m--;                        /* Zap leftover %s & *s */
   return (m >= ma) ? NOMATCH : MATCH;   /* Start of both = match */
 }
+
+static inline int
+comp_with_mask(void *addr, void *dest, unsigned int mask)
+{
+  if (memcmp(addr, dest, mask / 8) == 0)
+  {
+    int n = mask / 8;
+    int m = ((-1) << (8 - (mask % 8)));
+
+    if (mask % 8 == 0 ||
+       (((unsigned char *) addr)[n] & m) == (((unsigned char *) dest)[n] & m))
+      return (1);
+  }
+  return (0);
+}
+
+/* match_cidr()
+ *
+ * Input - mask, address
+ * Ouput - 1 = Matched 0 = Did not match
+ */
+
+int
+match_cidr(const char *s1, const char *s2)
+{
+  sockname_t ipaddr, maskaddr;
+  char address[NICKLEN + UHOSTLEN + 6] = "", mask[NICKLEN + UHOSTLEN + 6] = "", *ipmask = NULL, *ip = NULL, *len = NULL;
+  int cidrlen, aftype;
+
+  egg_bzero(&ipaddr, sizeof(ipaddr));
+  egg_bzero(&maskaddr, sizeof(maskaddr));
+
+  strcpy(mask, s1);
+  strcpy(address, s2);
+
+  ipmask = strrchr(mask, '@');
+  if(ipmask == NULL)
+    return 0;
+
+  *ipmask++ = '\0';
+
+  ip = strrchr(address, '@');
+  if(ip == NULL)
+    return 0;
+  *ip++ = '\0';
+
+  len = strrchr(ipmask, '/');
+  if(len == NULL)
+    return 0;
+
+  *len++ = '\0';
+
+  cidrlen = atoi(len);
+  if(cidrlen == 0)
+    return 0;
+
+  if (strchr(ip, ':') && strchr(ipmask, ':'))
+    aftype = ipaddr.family = maskaddr.family = AF_INET6;
+  else if (!strchr(ip, ':') && !strchr(ipmask, ':'))
+    aftype = ipaddr.family = maskaddr.family =  AF_INET;
+  else
+    return 0;
+
+  if (aftype == AF_INET6) {
+    inet_pton(aftype, ip, &ipaddr.u.ipv6.sin6_addr);
+    inet_pton(aftype, ipmask, &maskaddr.u.ipv6.sin6_addr);
+    if (comp_with_mask(&ipaddr.u.ipv6.sin6_addr.s6_addr, &maskaddr.u.ipv6.sin6_addr.s6_addr, cidrlen) && 
+       wild_match(mask, address))
+      return 1;
+  } else if (aftype == AF_INET) {
+    inet_pton(aftype, ip, &ipaddr.u.ipv4.sin_addr);
+    inet_pton(aftype, ipmask, &maskaddr.u.ipv4.sin_addr);
+    if (comp_with_mask(&ipaddr.u.ipv4.sin_addr.s_addr, &maskaddr.u.ipv4.sin_addr.s_addr, cidrlen) && 
+       wild_match(mask, address))
+      return 1;
+  }
+  return 0;
+}
+

+ 2 - 0
src/match.h

@@ -14,4 +14,6 @@ int _wild_match_per(register unsigned char *, register unsigned char *);
 //int wild_match(register char *, register char *);
 //int wild_match_per(register char *, register char *);
 
+int match_cidr(const char *, const char *);
+
 #endif /* !_MATCH_H */

+ 2 - 1
src/mod/irc.mod/chan.c

@@ -565,7 +565,8 @@ static void kick_all(struct chanset_t *chan, char *hostmask, const char *comment
     sprintf(s, "%s!%s", m->nick, m->userhost);
     get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, chan->dname);
     if (me_op(chan) &&
-	wild_match(hostmask, s) && !chan_sentkick(m) &&
+	(wild_match(hostmask, s) || match_cidr(hostmask, s)) && 
+        !chan_sentkick(m) &&
 	!match_my_nick(m->nick) && !chan_issplit(m) &&
 	!(use_exempts &&
 	  ((bantype && (isexempted(chan, s) || (chan->ircnet_status & CHAN_ASKED_EXEMPTS))) ||

+ 6 - 5
src/mod/irc.mod/irc.c

@@ -517,8 +517,8 @@ getin_request(char *botnick, char *code, char *par)
 
     mr = &global_bans;
     while (*mr) {
-      if (wild_match((*mr)->mask, host) || wild_match((*mr)->mask, ip4host) ||
-          wild_match((*mr)->mask, ip6host)) {
+      if (wild_match((*mr)->mask, host) || wild_match((*mr)->mask, ip4host) || wild_match((*mr)->mask, ip6host) || 
+          match_cidr((*mr)->mask, ip4host) || match_cidr((*mr)->mask, ip6host)) {
         if (!noshare) {
           shareout("-b %s\n", (*mr)->mask);
         }
@@ -539,8 +539,8 @@ getin_request(char *botnick, char *code, char *par)
     }
     mr = &chan->bans;
     while (*mr) {
-      if (wild_match((*mr)->mask, host) || wild_match((*mr)->mask, ip4host) ||
-          wild_match((*mr)->mask, ip6host)) {
+      if (wild_match((*mr)->mask, host) || wild_match((*mr)->mask, ip4host) || wild_match((*mr)->mask, ip6host) ||
+          match_cidr((*mr)->mask, ip4host) || match_cidr((*mr)->mask, ip6host)) {
         if (!noshare) {
           shareout("-bc %s %s\n", chan->dname, (*mr)->mask);
         }
@@ -559,7 +559,8 @@ getin_request(char *botnick, char *code, char *par)
       }
     }
     for (struct maskstruct *b = chan->channel.ban; b->mask[0]; b = b->next) {
-      if (wild_match(b->mask, host) || wild_match(b->mask, ip4host) || wild_match(b->mask, ip6host)) {
+      if (wild_match(b->mask, host) || wild_match(b->mask, ip4host) || wild_match(b->mask, ip6host) ||
+          match_cidr(b->mask, ip4host) || match_cidr(b->mask, ip6host)) {
         add_mode(chan, '-', 'b', b->mask);
         putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed active ban %s", botnick, nick, chan->dname,
                b->mask);

+ 1 - 1
src/mod/irc.mod/mode.c

@@ -730,7 +730,7 @@ got_ban(struct chanset_t *chan, memberlist *m, char *mask, char *isserver)
     register maskrec *b = NULL;
     char resn[512] = "";
 
-    /* The point of this cycle crap is to first check chan->bans then global_bans */
+    /* The point of this cycle crap is to first check chan->bans then global_bans for a reason */
     for (int cycle = 0; cycle < 2; cycle++) {
       for (b = cycle ? chan->bans : global_bans; b; b = b->next) {
         if (wild_match(b->mask, mask)) {

+ 4 - 0
src/socket.h

@@ -24,6 +24,10 @@ typedef struct {
 #endif
         } u;
 } sockname_t;
+
+//#define SOCKNAME_INADDR(x) (((x).family == AF_INET6) ? x.u.ipv6.sin6_addr : x.u.ipv4.sin_addr)
+//#define SOCKNAME_ADDR(x) (((x).family == AF_INET6) ? x.u.ipv6.sin6_addr.s6_addr : x.u.ipv4.sin_addr.s_addr)
+
 int socket_name(sockname_t *name, const char *ipaddr, port_t port);