netfilter: nf_conntrack_irc: Tighten matching on DCC message

CTCP messages should only be at the start of an IRC message, not
anywhere within it.

While the helper only decodes packes in the ORIGINAL direction, its
possible to make a client send a CTCP message back by empedding one into
a PING request.  As-is, thats enough to make the helper believe that it
saw a CTCP message.

Fixes: 869f37d8e4 ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
Signed-off-by: David Leadbeater <dgl@dgl.cx>
Signed-off-by: Florian Westphal <fw@strlen.de>
This commit is contained in:
David Leadbeater 2022-08-26 14:56:57 +10:00 committed by Florian Westphal
parent 25b327d4f8
commit e8d5dfd1d8
1 changed files with 28 additions and 6 deletions

View File

@ -157,15 +157,37 @@ static int help(struct sk_buff *skb, unsigned int protoff,
data = ib_ptr;
data_limit = ib_ptr + datalen;
/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
* 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
while (data < data_limit - (19 + MINMATCHLEN)) {
if (memcmp(data, "\1DCC ", 5)) {
/* Skip any whitespace */
while (data < data_limit - 10) {
if (*data == ' ' || *data == '\r' || *data == '\n')
data++;
else
break;
}
/* strlen("PRIVMSG x ")=10 */
if (data < data_limit - 10) {
if (strncasecmp("PRIVMSG ", data, 8))
goto out;
data += 8;
}
/* strlen(" :\1DCC SENT t AAAAAAAA P\1\n")=26
* 7+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=26
*/
while (data < data_limit - (21 + MINMATCHLEN)) {
/* Find first " :", the start of message */
if (memcmp(data, " :", 2)) {
data++;
continue;
}
data += 2;
/* then check that place only for the DCC command */
if (memcmp(data, "\1DCC ", 5))
goto out;
data += 5;
/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
/* we have at least (21+MINMATCHLEN)-(2+5) bytes valid data left */
iph = ip_hdr(skb);
pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
@ -181,7 +203,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
pr_debug("DCC %s detected\n", dccprotos[i]);
/* we have at least
* (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
* (21+MINMATCHLEN)-7-dccprotos[i].matchlen bytes valid
* data left (== 14/13 bytes) */
if (parse_dcc(data, data_limit, &dcc_ip,
&dcc_port, &addr_beg_p, &addr_end_p)) {