Limit list replies of LIST, WHO, WHOIS, and MAX_RPL_WHOWAS
authorAlexander Barton <alex@barton.de>
Fri, 6 Jan 2012 19:06:25 +0000 (20:06 +0100)
committerAlexander Barton <alex@barton.de>
Fri, 6 Jan 2012 19:06:25 +0000 (20:06 +0100)
Introduce new #define's MAX_RPL_LIST(100), MAX_RPL_WHO(25),
MAX_RPL_WHOIS(10), and MAX_RPL_WHOWAS(25).

src/ngircd/defines.h
src/ngircd/irc-channel.c
src/ngircd/irc-info.c

index 2613a358e9ffcc046a31f10c9853685ace688945..e75866811c3421358c79da33f3af4f15506e80b3 100644 (file)
 
 /* Defaults and limits for IRC commands */
 
-/** Default count of WHOWAS command replies */
-#define DEF_RPL_WHOWAS 5
+/** Max. number of LIST replies. */
+#define MAX_RPL_LIST 100
 
-/** Max. number of channel modes with arguments per MODE command */
+/** Max. number of channel modes with arguments per MODE command. */
 #define MAX_HNDL_MODES_ARG 5
 
+/** Max. number of WHO replies. */
+#define MAX_RPL_WHO 25
+
+/** Max. number of WHOIS replies. */
+#define MAX_RPL_WHOIS 10
+
+/** Default count of WHOWAS command replies. */
+#define DEF_RPL_WHOWAS 5
+
+/** Max count of WHOWAS command replies. */
+#define MAX_RPL_WHOWAS 25
+
 
 #endif
 
index 94a8a4d723db07661fdcff9bb794dffe9654f6f7..52ba0930caac5c9ab89f189dd684fe65e7976529 100644 (file)
@@ -31,6 +31,7 @@
 #include "match.h"
 #include "messages.h"
 #include "parse.h"
+#include "irc.h"
 #include "irc-info.h"
 #include "irc-write.h"
 #include "conf.h"
@@ -602,6 +603,7 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
        char *pattern;
        CHANNEL *chan;
        CLIENT *from, *target;
+       int count = 0;
 
        assert(Client != NULL);
        assert(Req != NULL);
@@ -654,12 +656,17 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
                                /* Gotcha! */
                                if (!strchr(Channel_Modes(chan), 's')
                                    || Channel_IsMemberOf(chan, from)) {
+                                       if (IRC_CheckListTooBig(from, count,
+                                                                MAX_RPL_LIST,
+                                                                "LIST"))
+                                               break;
                                        if (!IRC_WriteStrClient(from,
                                             RPL_LIST_MSG, Client_ID(from),
                                             Channel_Name(chan),
                                             Channel_MemberCount(chan),
                                             Channel_Topic( chan )))
                                                return DISCONNECTED;
+                                       count++;
                                }
                        }
                        chan = Channel_Next(chan);
@@ -672,6 +679,7 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
                        pattern = NULL;
        }
 
+       IRC_SetPenalty(from, 2);
        return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from));
 } /* IRC_LIST */
 
index 8c87d9320789fa00b1b277fcece7171c6c2f1777..fd4cbee4948c23870dd3a3c04da2c6e8b632b3da 100644 (file)
@@ -37,6 +37,7 @@
 #include "match.h"
 #include "tool.h"
 #include "parse.h"
+#include "irc.h"
 #include "irc-write.h"
 
 #include "exp.h"
@@ -833,6 +834,7 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
        const char *chan_user_modes;
        char flags[8];
        CLIENT *c;
+       int count = 0;
 
        assert( Client != NULL );
        assert( Chan != NULL );
@@ -855,6 +857,9 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
 
                is_visible = strchr(client_modes, 'i') == NULL;
                if (is_member || is_visible) {
+                       if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
+                               break;
+
                        strcpy(flags, who_flags_status(client_modes));
                        if (is_ircop)
                                strlcat(flags, "*", sizeof(flags));
@@ -866,6 +871,7 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
                        if (!write_whoreply(Client, c, Channel_Name(Chan),
                                            flags))
                                return DISCONNECTED;
+                       count++;
                }
        }
        return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
@@ -889,6 +895,7 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
        CHANNEL *chan;
        bool client_match, is_visible;
        char flags[4];
+       int count = 0;
 
        assert (Client != NULL);
 
@@ -939,13 +946,16 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
                if (!is_visible)        /* target user is not visible */
                        continue;
 
+               if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
+                       break;
+
                strcpy(flags, who_flags_status(Client_Modes(c)));
                if (strchr(Client_Modes(c), 'o'))
                        strlcat(flags, "*", sizeof(flags));
 
                if (!write_whoreply(Client, c, "*", flags))
                        return DISCONNECTED;
-
+               count++;
        }
 
        return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
@@ -1182,7 +1192,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
                 *  - no wildcards for remote clients
                 *  - only one wildcard target per local client
                 *
-                *  also, at most ten matches are returned.
+                *  Also, at most MAX_RPL_WHOIS matches are returned.
                 */
                if (!has_wildcards || is_remote) {
                        c = Client_Search(query);
@@ -1208,13 +1218,18 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
                got_wildcard = true;
                IRC_SetPenalty(Client, 3);
 
-               for (c = Client_First(); c && match_count < 10; c = Client_Next(c)) {
+               for (c = Client_First(); c; c = Client_Next(c)) {
+                       if (IRC_CheckListTooBig(Client, match_count,
+                                           MAX_RPL_WHOIS, "WHOIS"))
+                               break;
+
                        if (Client_Type(c) != CLIENT_USER)
                                continue;
                        if (!MatchCaseInsensitive(query, Client_ID(c)))
                                continue;
                        if (!IRC_WHOIS_SendReply(Client, from, c))
                                return DISCONNECTED;
+
                        match_count++;
                }
 
@@ -1310,7 +1325,7 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
        if (Req->argc > 1) {
                max = atoi(Req->argv[1]);
                if (max < 1)
-                       max = MAX_WHOWAS;
+                       max = MAX_RPL_WHOWAS;
        }
 
        /*