summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2012-01-06 20:06:25 +0100
committerAlexander Barton <alex@barton.de>2012-01-06 20:06:25 +0100
commitc5beca8aabab6d1822f63e86e5db02649d7b1a41 (patch)
tree5ad5cf00ee0fbccc3139cdb8f4a31110b2405243
parentf8405b1a4f032a125372b03711f6bed1ecac2bd6 (diff)
downloadngircd-c5beca8aabab6d1822f63e86e5db02649d7b1a41.tar.gz
ngircd-c5beca8aabab6d1822f63e86e5db02649d7b1a41.zip
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).
-rw-r--r--src/ngircd/defines.h18
-rw-r--r--src/ngircd/irc-channel.c8
-rw-r--r--src/ngircd/irc-info.c23
3 files changed, 42 insertions, 7 deletions
diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h
index 2613a358..e7586681 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 94a8a4d7..52ba0930 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 8c87d932..fd4cbee4 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;
 	}
 
 	/*