Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 468adf7a authored by David Leadbeater's avatar David Leadbeater Committed by Greg Kroah-Hartman
Browse files

netfilter: nf_conntrack_irc: Tighten matching on DCC message



[ Upstream commit e8d5dfd1d8747b56077d02664a8838c71ced948e ]

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: 869f37d8 ("[NETFILTER]: nf_conntrack/nf_nat: add IRC helper port")
Signed-off-by: default avatarDavid Leadbeater <dgl@dgl.cx>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 9431ef7d
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -150,15 +150,37 @@ static int help(struct sk_buff *skb, unsigned int protoff,
	data = ib_ptr;
	data_limit = ib_ptr + skb->len - dataoff;

	/* 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",
@@ -174,7 +196,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)) {