repo: ngircd
action: commit
revision: 
path_from: 
revision_from: c5beca8aabab6d1822f63e86e5db02649d7b1a41:
path_to: 
revision_to: 
git.thebackupbox.net
ngircd
git clone git://git.thebackupbox.net/ngircd
commit c5beca8aabab6d1822f63e86e5db02649d7b1a41
Author: Alexander Barton 
Date:   Fri Jan 6 20:06:25 2012 +0100

    Limit list replies of LIST, WHO, WHOIS, and MAX_RPL_WHOWAS

    Introduce new #define's MAX_RPL_LIST(100), MAX_RPL_WHO(25),
    MAX_RPL_WHOIS(10), and MAX_RPL_WHOWAS(25).

diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h
index 2613a358e9ffcc046a31f10c9853685ace688945..
index ..e75866811c3421358c79da33f3af4f15506e80b3 100644
--- a/src/ngircd/defines.h
+++ b/src/ngircd/defines.h
@@ -178,12 +178,24 @@

 /* 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

diff --git a/src/ngircd/irc-channel.c b/src/ngircd/irc-channel.c
index 94a8a4d723db07661fdcff9bb794dffe9654f6f7..
index ..52ba0930caac5c9ab89f189dd684fe65e7976529 100644
--- a/src/ngircd/irc-channel.c
+++ b/src/ngircd/irc-channel.c
@@ -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 */

diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c
index 8c87d9320789fa00b1b277fcece7171c6c2f1777..
index ..fd4cbee4948c23870dd3a3c04da2c6e8b632b3da 100644
--- a/src/ngircd/irc-info.c
+++ b/src/ngircd/irc-info.c
@@ -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;
 	}

 	/*

-----END OF PAGE-----