]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/numeric.c
Fix use-after-free while handling ERROR during client login
[ngircd-alex.git] / src / ngircd / numeric.c
index da863e4d48d25ecda53186f0d360f02c158fa9e3..380b9078b210deb9a6853cf2c966357efec75481 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
  *
  * 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
@@ -145,7 +145,27 @@ Announce_Server(CLIENT * Client, CLIENT * Server)
 #ifdef IRCPLUS
 
 /**
- * Synchronize invite, ban, G- and K-Line lists between servers.
+ * Send a specific list to a remote server.
+ */
+static bool
+Send_List(CLIENT *Client, CHANNEL *Chan, struct list_head *Head, char Type)
+{
+       struct list_elem *elem;
+
+       elem = Lists_GetFirst(Head);
+       while (elem) {
+               if (!IRC_WriteStrClient(Client, "MODE %s +%c %s",
+                                       Channel_Name(Chan), Type,
+                                       Lists_GetMask(elem))) {
+                       return DISCONNECTED;
+               }
+               elem = Lists_GetNext(elem);
+       }
+       return CONNECTED;
+}
+
+/**
+ * Synchronize invite, ban, except, and G-Line lists between servers.
  *
  * @param Client New server.
  * @return CONNECTED or DISCONNECTED.
@@ -156,6 +176,7 @@ Synchronize_Lists(CLIENT * Client)
        CHANNEL *c;
        struct list_head *head;
        struct list_elem *elem;
+       time_t t;
 
        assert(Client != NULL);
 
@@ -163,9 +184,10 @@ Synchronize_Lists(CLIENT * Client)
        head = Class_GetList(CLASS_GLINE);
        elem = Lists_GetFirst(head);
        while (elem) {
+               t = Lists_GetValidity(elem) - time(NULL);
                if (!IRC_WriteStrClient(Client, "GLINE %s %ld :%s",
                                        Lists_GetMask(elem),
-                                       Lists_GetValidity(elem) - time(NULL),
+                                       t > 0 ? (long)t : 0,
                                        Lists_GetReason(elem)))
                        return DISCONNECTED;
                elem = Lists_GetNext(elem);
@@ -173,30 +195,12 @@ Synchronize_Lists(CLIENT * Client)
 
        c = Channel_First();
        while (c) {
-               /* ban list */
-               head = Channel_GetListBans(c);
-               elem = Lists_GetFirst(head);
-               while (elem) {
-                       if (!IRC_WriteStrClient(Client, "MODE %s +b %s",
-                                               Channel_Name(c),
-                                               Lists_GetMask(elem))) {
-                               return DISCONNECTED;
-                       }
-                       elem = Lists_GetNext(elem);
-               }
-
-               /* invite list */
-               head = Channel_GetListInvites(c);
-               elem = Lists_GetFirst(head);
-               while (elem) {
-                       if (!IRC_WriteStrClient(Client, "MODE %s +I %s",
-                                               Channel_Name(c),
-                                               Lists_GetMask(elem))) {
-                               return DISCONNECTED;
-                       }
-                       elem = Lists_GetNext(elem);
-               }
-
+               if (!Send_List(Client, c, Channel_GetListExcepts(c), 'e'))
+                       return DISCONNECTED;
+               if (!Send_List(Client, c, Channel_GetListBans(c), 'b'))
+                       return DISCONNECTED;
+               if (!Send_List(Client, c, Channel_GetListInvites(c), 'I'))
+                       return DISCONNECTED;
                c = Channel_Next(c);
        }
        return CONNECTED;
@@ -214,7 +218,8 @@ Send_CHANINFO(CLIENT * Client, CHANNEL * Chan)
        bool has_k, has_l;
 
 #ifdef DEBUG
-       Log(LOG_DEBUG, "Sending CHANINFO commands ...");
+       Log(LOG_DEBUG, "Sending CHANINFO commands for \"%s\" ...",
+           Channel_Name(Chan));
 #endif
 
        modes = Channel_Modes(Chan);