From c5beca8aabab6d1822f63e86e5db02649d7b1a41 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Fri, 6 Jan 2012 20:06:25 +0100 Subject: [PATCH 1/1] 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). --- src/ngircd/defines.h | 18 +++++++++++++++--- src/ngircd/irc-channel.c | 8 ++++++++ src/ngircd/irc-info.c | 23 +++++++++++++++++++---- 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; } /* -- 2.39.2