]> jfr.im git - irc/quakenet/newserv.git/blobdiff - glines/glines_handler.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / glines / glines_handler.c
index 66330bcfb29cf64ab67b2b22a01fe48929b044de..52b60b8b740b94f3a09a0e3408f6b26ba011f5b1 100644 (file)
@@ -3,13 +3,20 @@
 #include "../localuser/localuserchannel.h"
 #include "glines.h"
 
+//#define DEBUG
+
+#ifdef DEBUG
+#define Debug(...) Error("debuggline", ERR_DEBUG, ##__VA_ARGS__)
+#else
+#define Debug(...)
+#endif
+
 /*
   <prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>] [<lifetime>] [:<reason>]
 */
 
 int handleglinemsg(void *source, int cargc, char **cargv) {
   char *sender = (char *)source;
-  char *target;
   char *mask;
   char *reason;
   char *creator;
@@ -18,10 +25,12 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
   long creatornum;
   gline *agline;
   nick *np;
+  glinebuf gbuf;
 
   /**
    * Valid GL tokens have X params:
    * 2: Local modification to a local gline - ignored by services
+   * 4: ulined GL
    * 5: 1.3.x GL Token
    * 6: 1.4.x GL Token - adds lifetime parameter
    */
@@ -29,6 +38,9 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
     case 2:
       /* local modification which we reject later */
       break;
+    case 4:
+      /* ulined GL */
+      break;
     case 5:
       /* 1.3.x GL Token */
       break;
@@ -56,7 +68,7 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
           Error("gline", ERR_WARNING, "Received gline from non-existant server");
           return CMD_ERROR; 
         } else {
-          creator = serverlist[(int)creatornum].name->content, HOSTLEN;
+          creator = serverlist[(int)creatornum].name->content;
         }
       break;
     case 5:
@@ -73,18 +85,14 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
       return CMD_ERROR;
   }
 
-  /* 1st param is target */
-  target = cargv[0];
-
-  /* anything other than a global G-Line is irrelevant */
-  if (strcmp(target, "*") != 0) {
-    Error("gline", ERR_WARNING, "Received local g-line from %s - do they realise we're a service?", sender);
-    return CMD_ERROR;
-  }
-
   /* 2nd param is mask */
   mask = cargv[1];
 
+  if (*mask == '%') {
+    flags |= GLINE_DESTROY;
+    mask++;
+  }
+
   switch (*mask) {
     case '+':
       flags |= GLINE_ACTIVATE;
@@ -109,6 +117,8 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
     switch (cargc) {
       case 4:
         /* asuka U:d, no lastmod */
+        lastmod = 0;
+        lifetime = expire;
         reason = cargv[3];
         break;
       case 5:
@@ -128,36 +138,40 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
          return CMD_ERROR;
     }
 
-    Error("debuggline", ERR_WARNING, "GL Received: Creator %s, Mask %s, Reason %s, Expire %lu, Lastmod %lu, Lifetime %lu", creator, mask, reason, expire, lastmod, lifetime);   
+    Debug("GL Received: Creator %s, Mask %s, Reason %s, Expire %lu, Lastmod %lu, Lifetime %lu", creator, mask, reason, expire, lastmod, lifetime);   
 
-    agline = gline_find(mask);
+    agline = findgline(mask);
 
     if (agline) {
-      if (agline->flags & GLINE_ACTIVE) { 
-        Error("debuggline", ERR_WARNING, "Duplicate Gline recieved for %s - old lastmod %lu, expire %lu, lifetime %lu, reason %s, creator %s", mask, agline->lastmod, agline->expire, agline->lifetime, agline->reason->content, agline->creator->content);
+      Debug("Update for existing gline received for %s - old lastmod %lu, expire %lu, lifetime %lu, reason %s, creator %s", mask, agline->lastmod, agline->expire, agline->lifetime, agline->reason ? agline->reason->content : "", agline->creator->content);
+
+      agline->flags |= GLINE_ACTIVE;
+
+      /* check lastmod then assume the new gline is authoritive */
+      if (lastmod > agline->lastmod) {
+        agline->lastmod = lastmod;
+        agline->expire = expire;
+        agline->lifetime = lifetime;
+        freesstring(agline->creator);
+        agline->creator = getsstring(creator, 255);
+        freesstring(agline->reason);
+        agline->reason = getsstring(reason, 255); 
       } else {
-        /* we're reactivating a gline - check lastmod then assume the new gline is authoritive */
-        if (lastmod > agline->lastmod) {
-          agline->lastmod = lastmod;
-          agline->expire = expire;
-          agline->lifetime = lifetime;
-          agline->creator = getsstring(creator, 255);
-          freesstring(agline->reason);
-          agline->reason = getsstring(reason, 255); 
-          agline->flags |= GLINE_ACTIVE;
-        } else {
-          Error("debuggline", ERR_WARNING, "received a gline with a lower lastmod");
-          /* @@@TODO resend our gline ? */
-        } 
-      }
-      /* TODO */
-      return CMD_ERROR;
+        Debug("received a gline with a lower lastmod");
+        /* Don't send our gline as that might cause loops in case we don't understand the gline properly. */
+      } 
+
+      return CMD_OK;
     } else {
-      gline_add(creator, mask, reason, expire, lastmod, lifetime); 
+      glinebufinit(&gbuf, 0);
+      glinebufadd(&gbuf, mask, creator, reason, expire, lastmod, lifetime);
+      glinebufcommit(&gbuf, 0);
     } 
   } else if (flags & GLINE_DEACTIVATE) {
     /* deactivate gline */
-    if ((agline = gline_find(mask))) {
+    agline = findgline(mask);
+
+    if (agline) {
       switch (cargc) {
         case 2:
           /* asuka U:d, no last mod */
@@ -166,12 +180,22 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
         case 5:
           /* asuka last mod */
           lastmod = atoi(cargv[3]);
-          gline_deactivate(agline, lastmod, 0);
+          
+          if (flags & GLINE_DESTROY)
+            gline_destroy(agline, lastmod, 0);
+          else
+            gline_deactivate(agline, lastmod, 0);
+
           break;
         case 6:
           /* snircd */
           lastmod = atoi(cargv[3]);
-          gline_deactivate(agline, lastmod, 0);
+
+          if (flags & GLINE_DESTROY)
+            gline_destroy(agline, lastmod, 0);
+          else
+            gline_deactivate(agline, lastmod, 0);
+
           break;
         default:
           Error("gline", ERR_WARNING, "Gline Deactivate with invalid number (%d) of arguments", cargc);
@@ -180,13 +204,11 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
 
       return CMD_OK;
     } else {
+       if (cargc < 5)
+         return; /* U:lined gline, we're done */
        Error("gline", ERR_WARNING, "Gline addition - adding deactivated gline - mask not found (%s)", mask);
        expire = abs_expire(atoi(cargv[2]));
        switch (cargc) {
-         case 4:
-           /* asuka U:d, no lastmod */
-           reason = cargv[3];
-           break;
          case 5:
            /*asuka lastmod */
            lastmod = atoi(cargv[3]);
@@ -204,20 +226,25 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
            return CMD_ERROR;
       }
 
-      agline = gline_add(creator, mask, reason, expire, lastmod, lifetime);
+      glinebufinit(&gbuf, 0);
+      agline = glinebufadd(&gbuf, mask, creator, reason, expire, lastmod, lifetime);
 
       if (!agline) {
+        glinebufabort(&gbuf);
         Error("gline", ERR_WARNING, "gline_add failed");
         return CMD_ERROR;
       }
 
       gline_deactivate(agline, lastmod, 0);
+      glinebufcommit(&gbuf, 0);
 
       return CMD_OK;
     }
   } else {
     /* modification - only snircd 1.4.x */
-    if ((agline = gline_find(mask))) {
+    agline = findgline(mask);
+
+    if (agline) {
       expire = abs_expire(atoi(cargv[2]));
       lastmod = atoi(cargv[3]);
       lifetime = atoi(cargv[4]);
@@ -231,13 +258,12 @@ int handleglinemsg(void *source, int cargc, char **cargv) {
         freesstring(agline->reason);
         agline->reason = getsstring(reason, 255);
       } else {
-        Error("debuggline", ERR_WARNING, "received a gline modification with a lower lastmod");
-        /* @@@TODO resend our gline ? */
+        Debug("received a gline modification with a lower lastmod");
       }
 
       return CMD_OK;
     } else {
-      Error("gline", ERR_WARNING, "Received modification for G-Line that does not exist for mask %s", mask);
+      Debug("Received modification for G-Line that does not exist for mask %s", mask);
       return CMD_ERROR;
     }
   }