]> jfr.im git - irc/blitzed-org/bopm.git/commitdiff
match.c, match.h:
authorandy <redacted>
Fri, 15 Feb 2002 04:57:29 +0000 (04:57 +0000)
committerandy <redacted>
Fri, 15 Feb 2002 04:57:29 +0000 (04:57 +0000)
IRC wildcard matching functions from dancer-hybrid.  match()
handles string matching and collapse() shortens a wildcard string
as far as possible.

config.h:
Added new config type; TYPE_LIST.  Multiple parameters of this
type are put into a linked list.

Added missing config_memfail() prototype.

config.c:
Added new config option EXCLUDE.  This is a list of wildcard
strings against which the host and IP address of connecting users
will be matched.  A user which matches any entry will not be
scanned.

Makefile.in:
Added new objects and dependencies for match.[cho]

irc.c, irc.h:
Added do_connect() function to avoid duplication.  This function
checks the users host and IP address against the EXCLUDE list and
provided there are no matches proceeds to do a DNSBL check and
proxy scan.

The above patch was contributed by Rob Levin/lilo @ OPN

Makefile.in
config.c
config.h
extern.h
irc.c
irc.h
match.c [new file with mode: 0644]
match.h [new file with mode: 0644]
scan.c

index dca723a66b8551e92dc56161639a8af1fb0a9845..1173b70361fa96e65c899218cd4f5a42889fc148 100644 (file)
@@ -16,19 +16,20 @@ CFLAGS += -pg
 LFLAGS += -pg
 endif
 
-objects = config.o dnsbl.o irc.o log.o main.o misc.o opercmd.o scan.o \
-          stats.o
+objects = config.o dnsbl.o irc.o log.o main.o match.o misc.o opercmd.o \
+         scan.o stats.o
 
-checker_obj = bopchecker.o config.o misc.o scan.o
+checker_obj = bopchecker.o config.o match.o misc.o scan.o
 
 all: bopm bopchecker
        rm -f *.da
 
-config.o:  setup.h config.h log.h
+config.o:  setup.h config.h log.h match.h
 dnsbl.o:   setup.h dnsbl.h extern.h irc.h log.h opercmd.h scan.h
-irc.o:     setup.h config.h dnsbl.h extern.h irc.h log.h opercmd.h options.h scan.h
+irc.o:     setup.h config.h dnsbl.h extern.h irc.h log.h match.h opercmd.h options.h scan.h
 log.o:     setup.h extern.h log.h
 main.o:    setup.h extern.h irc.h log.h opercmd.h scan.h stats.h
+match.o:   setup.h match.h
 misc.o:    setup.h extern.h misc.h
 opercmd.o: setup.h extern.h irc.h log.h misc.h opercmd.h scan.h
 scan.o:    setup.h config.h dnsbl.h extern.h irc.h log.h opercmd.h scan.h stats.h
index b3129050f2596f06c18386848cd53d77b26ad646..152407d71502b08f7be68e350097d1964e6424dc 100644 (file)
--- a/config.c
+++ b/config.c
@@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software
 #include "log.h"
 #include "misc.h"
 #include "extern.h"
+#include "match.h"
 
 /* Global Configuration Variables */
 
@@ -57,6 +58,7 @@ char *CONF_SENDMAIL        = 0;
 char *CONF_HELP_EMAIL      = 0;
 char *CONF_AWAY            = 0;
 char *CONF_TARGET_STRING   = 0;
+string_list *CONF_EXCLUDE  = 0;
 
 int  CONF_SCANPORT         = 0;
 int  CONF_PORT             = 0;
@@ -88,6 +90,7 @@ config_hash hash[] = {
        {"HELP_EMAIL",          TYPE_STRING, 1,0,    &CONF_HELP_EMAIL         },
        {"AWAY",                TYPE_STRING, 1,0,    &CONF_AWAY               },
        {"TARGET_STRING",       TYPE_STRING, 1,0,    &CONF_TARGET_STRING      },
+       {"EXCLUDE",             TYPE_LIST,   0,0,    &CONF_EXCLUDE            },
        {0,                     0,           0,0,    0                        },
 };
 
@@ -102,7 +105,9 @@ void config_load(char *filename)
     char line[1024];  /* 1k buffer for reading the file */
 
     char *key;
-    char *args;   
+    char *args;
+
+    string_list *list, *oldlist;
 
     int i;
 
@@ -124,6 +129,7 @@ void config_load(char *filename)
                   break;
               case TYPE_INT:
                   *(int *) hash[i].var = 0;
+                 break;
           }
          hash[i].reqmet = 0;
       }
@@ -154,13 +160,47 @@ void config_load(char *filename)
                             case TYPE_INT:
                                  *(int *) hash[i].var = atoi(args);
                                  break;
+                           case TYPE_LIST:
+                                list = malloc(sizeof(string_list));
+                                if(!list)
+                                   config_memfail();
+                                list->next = NULL;
+                                list->text = strdup(args);
+                                if(!list->text)
+                                   config_memfail();
+                                collapse(list->text);
+                                oldlist = * (string_list **) (hash[i].var);
+                                if(oldlist)
+                                 {
+                                   while(oldlist)
+                                    {
+                                      if(strcasecmp(args, oldlist->text))
+                                       {
+                                         if(oldlist->next)
+                                            oldlist = oldlist->next;
+                                         else
+                                          {
+                                            oldlist->next = list;
+                                            oldlist = NULL;
+                                          }
+                                       }
+                                      else
+                                       {
+                                         free(list);
+                                         oldlist = NULL;
+                                       }
+                                    }
+                                 }
+                                else
+                                 {
+                                   * (string_list **) (hash[i].var) = list;
+                                 }
+                               break;
                         }
                        hash[i].reqmet = 1;
                 }
-
       }
 
-
   fclose(in);
   config_checkreq(); /* Check required parameters */
 }
index 8b6f97cdf27dc80133327cf55e323c79656a3cbe..39b946d2d12335a1952ce58695cb8eeb05710e82 100644 (file)
--- a/config.h
+++ b/config.h
@@ -3,8 +3,9 @@
 
       typedef struct config_hash config_hash;
 
-      #define TYPE_STRING 1
-      #define TYPE_INT 2
+#define TYPE_STRING 1
+#define TYPE_INT 2
+#define TYPE_LIST 3
 
       struct config_hash
        {
            void *var;
        };
 
+      typedef struct string_list string_list;
+      
+      struct string_list
+       {
+         string_list *next;
+        char *text;
+       };
+               
        /* Config Functions */
 
        void config_load(char *filename);
        void config_checkreq();
+       void config_memfail();
 
 #endif
index 5b1996fac788fbf1a12a67197036435e90771a67..161a7c3b2253da0aa2b63b844f2932caf919ddbf 100644 (file)
--- a/extern.h
+++ b/extern.h
@@ -26,6 +26,7 @@
     extern char *CONF_HELP_EMAIL;
     extern char *CONF_AWAY;
     extern char *CONF_TARGET_STRING;
+    extern string_list *CONF_EXCLUDE;
 
     extern int   CONF_PORT;
     extern int   CONF_SCANPORT;
diff --git a/irc.c b/irc.c
index 78de468b395fb2f6a6cf553159d786f2dc5a5618..fc90b6e01773310e78eb7cc496996c02800c4c43 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -60,6 +60,7 @@ along with this program; if not, write to the Free Software
 #include "extern.h"
 #include "options.h"
 #include "version.h"
+#include "match.h"
 
 extern char *CONFFILE;
 
@@ -634,10 +635,8 @@ void irc_parse()
           irc_user = strtok(irc_user, "@"); /* username is everything before the '@' */
 
           irc_addr = strtok(NULL , ")");    /* irc_addr is everything between '@' and closing ')' */
-          if(CONF_DNSBL_ZONE && dnsbl_check(addr, irc_nick,
-                                            irc_user, irc_addr))
-             return;
-          scan_connect(addr, irc_addr, irc_nick, irc_user, 0, conn_notice);
+
+          do_connect(addr, irc_nick, irc_user, irc_addr, conn_notice);
      } 
     
     if(token[0][0] == ':')
@@ -688,10 +687,7 @@ void irc_parse()
                   irc_user = strtok(irc_user, "@"); /* username is everything before the '@' */
                      
                   irc_addr = strtok(NULL , ")");    /* irc_addr is everything between '@' and closing ')' */
-                  if(CONF_DNSBL_ZONE && dnsbl_check(addr, irc_nick,
-                                                   irc_user, irc_addr))
-                    return;
-                  scan_connect(addr, irc_addr, irc_nick, irc_user, 0, conn_notice);
+                 do_connect(addr, irc_nick, irc_user, irc_addr, conn_notice);
             }
      }
 
@@ -740,3 +736,28 @@ void irc_timer()
         time(&LAST_REAP_TIME);
      } 
 }
+
+void do_connect(char *addr, char *irc_nick, char *irc_user, char *irc_addr,
+               char *conn_notice)
+{
+   string_list *list;
+
+   /* check that neither the user's IP nor host matches anything in our
+    * exclude list
+    */
+   for(list = (string_list *) CONF_EXCLUDE; list; list = list->next)
+    {
+      if(match(list->text, addr) || match(list->text, irc_addr))
+       {
+         if(OPT_DEBUG)
+           log("SCAN -> excluded user %s!%s@%s", irc_nick, irc_user, irc_addr);
+
+         return;
+       }
+    }
+   
+   if(CONF_DNSBL_ZONE && dnsbl_check(addr, irc_nick, irc_user, irc_addr))
+      return;
+
+   scan_connect(addr, irc_addr, irc_nick, irc_user, 0, conn_notice);
+}
diff --git a/irc.h b/irc.h
index 0ea03a40eaa966ce1ba85fe03a51f2b4e9a0479c..7a6c644852a9158ea1e783bb8e350f85afeb9a72 100644 (file)
--- a/irc.h
+++ b/irc.h
@@ -14,8 +14,9 @@
       void irc_timer();
       void irc_send(char *data, ...);       
 
-      
       void do_invite();
       void do_privmsg();
       void do_perform();
+      void do_connect(char *addr, char *irc_nick, char *irc_user,
+                     char *irc_addr, char *conn_notice);
 #endif
diff --git a/match.c b/match.c
new file mode 100644 (file)
index 0000000..167dafe
--- /dev/null
+++ b/match.c
@@ -0,0 +1,223 @@
+/*
+    Copyright (C) 1990-2002 by Jarkko Oikarinen, Thomas Helvey,
+    Douglas A Lewis and the hybrid ircd development team.  Minor
+    changes were made by and are copyrighted by Robert Levin of
+    the dancer-ircd development team.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version 1
+    of the License, or (at your option) any later version.
+    
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    
+    You should have received a copy of the GNU General Public
+    License along with this program; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA  02111-1307, USA.
+   
+*/
+
+#include <assert.h>
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <stdarg.h>
+# include <string.h>
+#endif
+
+#include <time.h>
+#include <unistd.h>
+
+#include "match.h"
+
+#define ToLower(c) (ToLowerTab[(unsigned char)(c)])
+
+const unsigned char ToLowerTab[] = {
+       0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
+       0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
+       0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 
+       0x1e, 0x1f,
+       ' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
+       '*', '+', ',', '-', '.', '/',
+       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+       ':', ';', '<', '=', '>', '?',
+       '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+       'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+       't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^',
+       '_',
+       '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+       'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+       't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
+       0x7f,
+       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+       0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+       0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+       0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+       0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+       0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+       0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+       0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+       0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+       0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+       0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+       0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+#define MATCH_MAX_CALLS 512  /* ACK! This dies when it's less that this and
+                               we have long lines to parse */
+
+/*
+ * Compare if a given string (name) matches the given mask (which can
+ * contain wild cards: '*' - match any number of chars, '?' - match any
+ * single character.
+ *
+ * return 1, if match
+ *        0, if no match
+ */
+
+/*
+ * match()
+ * Iterative matching function, rather than recursive.
+ * Written by Douglas A Lewis (dalewis@acsu.buffalo.edu)
+ *
+ * behavior change - (Thomas Helvey <tomh@inxpress.net>)
+ *
+ * removed escape handling, none of the masks used with this function
+ * should contain an escape '\\' unless you are searching for one, it is no
+ * longer possible to escape * and ?.
+ *
+ * Moved calls rollup to function body, since match isn't recursive there
+ * isn't any reason to have it exposed to the file, this change also has
+ * the added benefit of making match reentrant. :)
+ *
+ * Added asserts, mask and name cannot be null.
+ *
+ * Changed ma and na to unsigned to get rid of casting.
+ *
+ * NOTICE: match is now a boolean operation, not a lexical comparison; if a
+ * line matches a mask, true (1) is returned, otherwise false (0) is
+ * returned.
+ */
+
+int match(const char *mask, const char *name)
+{
+       const unsigned char *m = (const unsigned char *)  mask;
+       const unsigned char *n = (const unsigned char *)  name;
+       const unsigned char *ma = (const unsigned char *) mask;
+       const unsigned char *na = (const unsigned char *) name;
+       int wild  = 0;
+       int calls = 0;
+
+       assert(0 != mask);
+       assert(0 != name);
+
+       if (!mask || !name)
+               return 0;
+
+       while (calls++ < MATCH_MAX_CALLS) {
+               if (*m == '*') {
+                       /* XXX - shouldn't need to spin here, the mask
+                        * should have been collapsed before match is
+                        * called
+                        */
+                       while (*m == '*')
+                               m++;
+
+                       wild = 1;
+                       ma = m;
+                       na = n;
+               }
+
+               if (!*m) {
+                       if (!*n)
+                               return 1;
+
+                       for (m--; (m > (const unsigned char *) mask) && (*m == '?'); m--)
+                               ; /* empty loop */
+
+                       if ((*m == '*') && (m > (const unsigned char *) mask))
+                               return 1;
+
+                       if (!wild)
+                               return 0;
+
+                       m = ma;
+                       n = ++na;
+               } else if (!*n) {
+                       /* XXX - shouldn't need to spin here, the mask
+                        * should have been collapsed before match is
+                        * called
+                        */
+                       while (*m == '*')
+                               m++;
+
+                       return (*m == 0);
+               }
+
+               if (ToLower(*m) != ToLower(*n) && *m != '?') {
+                       if (!wild)
+                               return 0;
+
+                       m = ma;
+                       n = ++na;
+               } else {
+                       if (*m)
+                               m++;
+
+                       if (*n)
+                               n++;
+               }
+       }
+       return 0;
+}
+                                       
+
+/*
+ * collapse a pattern string into minimal components.
+ * This particular version is "in place", so that it changes the pattern
+ * which is to be reduced to a "minimal" size.
+ *
+ * behavior modification (Thomas Helvey <tomh@inxpress.net>)
+ * Removed mask escapes, we don't escape wildcards or call match on a mask.
+ * This change is somewhat subtle, the old version converted \\*** to \\**,
+ * the new version blindly converts it to \\*.
+ *
+ * Removed code that did a lot of work but achieved nothing, testing showed
+ * that the code in test for '?' produced exactly the same results as code
+ * that ignored '?'. The only thing you can do with a mask is to remove
+ * adjacent '*' characters, attempting anything else breaks the re.
+ *
+ * convert adjacent *'s to a single *
+ */
+char *collapse(char *pattern)
+{
+       char *s = pattern;
+       char *s1;
+       char *t;
+
+       /* XXX - null pointers OK? */
+       if (s) {
+               for (; *s; s++) {
+                       if ('*' == *s) {
+                               t = s1 = s + 1;
+                               while ('*' == *t)
+                                       ++t;
+
+                               if (s1 != t) {
+                                       while ((*s1++ = *t++))
+                                               ; /* empty loop */
+                               }
+                       }
+               }
+       }
+       return pattern;
+}
+
diff --git a/match.h b/match.h
new file mode 100644 (file)
index 0000000..cce7077
--- /dev/null
+++ b/match.h
@@ -0,0 +1,7 @@
+#ifndef MATCH_H
+#define MATCH_H
+
+int match(const char *mask, const char *name);
+char *collapse(char *pattern);
+
+#endif    
diff --git a/scan.c b/scan.c
index 08c254def9c43508abf21516330561b2de32277a..461d2a6e4fc444e10c347b00b11e8a247b85dec1 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -174,7 +174,6 @@ void scan_establish(scan_struct *conn)
     /* Setup SCAN_LOCAL for local bind() */
     if(CONF_BINDSCAN)
      {
-
            if(!inet_aton(CONF_BINDSCAN, &(SCAN_LOCAL.sin_addr)))
             {
                  log("SCAN -> bind(): %s is an invalid address", CONF_BINDSCAN);