Limit the number of message targes, and suppress duplicates
This prevents an user from flooding the server using commands like this: PRIVMSG nick1,nick1,nick1,... Duplicate targets are suppressed silently (channels and clients). In addition, the maximum number of targets per PRIVMSG/NOTICE/... command are limited to MAX_HNDL_TARGETS (25). If there are more, the daemon sends the new 407 (ERR_TOOMANYTARGETS_MSG) numeric, containing the first target that hasn't been handled any more. Closes #187.
This commit is contained in:
parent
cedba36965
commit
49ab79d0e6
|
@ -206,6 +206,9 @@
|
||||||
/** 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
|
#define MAX_HNDL_MODES_ARG 5
|
||||||
|
|
||||||
|
/** Max. number of targets per PRIVMSG/NOTICE/... command. */
|
||||||
|
#define MAX_HNDL_TARGETS 25
|
||||||
|
|
||||||
/** Max. number of WHO replies. */
|
/** Max. number of WHO replies. */
|
||||||
#define MAX_RPL_WHO 25
|
#define MAX_RPL_WHO 25
|
||||||
|
|
||||||
|
|
|
@ -517,8 +517,10 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||||
CL2CHAN *cl2chan;
|
CL2CHAN *cl2chan;
|
||||||
CHANNEL *chan;
|
CHANNEL *chan;
|
||||||
char *currentTarget = Req->argv[0];
|
char *currentTarget = Req->argv[0];
|
||||||
char *lastCurrentTarget = NULL;
|
char *strtok_last = NULL;
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
|
char *targets[MAX_HNDL_TARGETS];
|
||||||
|
int i, target_nr = 0;
|
||||||
|
|
||||||
assert(Client != NULL);
|
assert(Client != NULL);
|
||||||
assert(Req != NULL);
|
assert(Req != NULL);
|
||||||
|
@ -558,10 +560,17 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||||
message = Req->argv[1];
|
message = Req->argv[1];
|
||||||
|
|
||||||
/* handle msgtarget = msgto *("," msgto) */
|
/* handle msgtarget = msgto *("," msgto) */
|
||||||
currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget);
|
currentTarget = strtok_r(currentTarget, ",", &strtok_last);
|
||||||
ngt_UpperStr(Req->command);
|
ngt_UpperStr(Req->command);
|
||||||
|
|
||||||
while (currentTarget) {
|
while (true) {
|
||||||
|
/* Make sure that there hasn't been such a target already: */
|
||||||
|
targets[target_nr++] = currentTarget;
|
||||||
|
for(i = 0; i < target_nr - 1; i++) {
|
||||||
|
if (strcasecmp(currentTarget, targets[i]) == 0)
|
||||||
|
goto send_next_target;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for and handle valid <msgto> of form:
|
/* Check for and handle valid <msgto> of form:
|
||||||
* RFC 2812 2.3.1:
|
* RFC 2812 2.3.1:
|
||||||
* msgto = channel / ( user [ "%" host ] "@" servername )
|
* msgto = channel / ( user [ "%" host ] "@" servername )
|
||||||
|
@ -725,9 +734,18 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||||
}
|
}
|
||||||
|
|
||||||
send_next_target:
|
send_next_target:
|
||||||
currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
|
currentTarget = strtok_r(NULL, ",", &strtok_last);
|
||||||
if (currentTarget)
|
if (!currentTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
Conn_SetPenalty(Client_Conn(Client), 1);
|
Conn_SetPenalty(Client_Conn(Client), 1);
|
||||||
|
|
||||||
|
if (target_nr >= MAX_HNDL_TARGETS) {
|
||||||
|
/* Too many targets given! */
|
||||||
|
return IRC_WriteErrClient(Client,
|
||||||
|
ERR_TOOMANYTARGETS_MSG,
|
||||||
|
currentTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CONNECTED;
|
return CONNECTED;
|
||||||
|
|
|
@ -110,6 +110,7 @@
|
||||||
#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel"
|
#define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel"
|
||||||
#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels"
|
#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels"
|
||||||
#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname"
|
#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname"
|
||||||
|
#define ERR_TOOMANYTARGETS_MSG "407 %s :Too many recipients"
|
||||||
#define ERR_NOORIGIN_MSG "409 %s :No origin specified"
|
#define ERR_NOORIGIN_MSG "409 %s :No origin specified"
|
||||||
#define ERR_INVALIDCAP_MSG "410 %s %s :Invalid CAP subcommand"
|
#define ERR_INVALIDCAP_MSG "410 %s %s :Invalid CAP subcommand"
|
||||||
#define ERR_NORECIPIENT_MSG "411 %s :No recipient given (%s)"
|
#define ERR_NORECIPIENT_MSG "411 %s :No recipient given (%s)"
|
||||||
|
|
|
@ -35,13 +35,13 @@ expect {
|
||||||
send "privmsg nick,nick :test\r"
|
send "privmsg nick,nick :test\r"
|
||||||
expect {
|
expect {
|
||||||
timeout { exit 1 }
|
timeout { exit 1 }
|
||||||
"@* PRIVMSG nick :test\r*@* PRIVMSG nick :test"
|
"@* PRIVMSG nick :test"
|
||||||
}
|
}
|
||||||
|
|
||||||
send "privmsg Nick,#testChannel,nick :test\r"
|
send "privmsg Nick,#testChannel,nick :test\r"
|
||||||
expect {
|
expect {
|
||||||
timeout { exit 1 }
|
timeout { exit 1 }
|
||||||
"@* PRIVMSG nick :test\r*401*@* PRIVMSG nick :test"
|
"@* PRIVMSG nick :test\r*401"
|
||||||
}
|
}
|
||||||
|
|
||||||
send "privmsg doesnotexist :test\r"
|
send "privmsg doesnotexist :test\r"
|
||||||
|
|
Loading…
Reference in New Issue