From patchwork Mon Jun 5 19:17:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790618 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=eCB/tXTi; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2v5g3Gz20Wv for ; Tue, 6 Jun 2023 05:20:23 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230150AbjFETUR (ORCPT ); Mon, 5 Jun 2023 15:20:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235496AbjFETTv (ORCPT ); Mon, 5 Jun 2023 15:19:51 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41CF710FA for ; Mon, 5 Jun 2023 12:19:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=b4Qv6qGM6iMZD+j0KGtrU39Ns6Lh6LvhbTRY7CMt1LE=; b=eCB/tXTidpY3F5a1g3nERAfK1j pPXzH+9nAdhQX7PJcslP/9R5Z3uubASnCpFP2OuBX6g6gXKJOV+plIlCPQJ1tw+iGE7kKvIJeHVDN K9aYbzs0+JM6kT1Pv1kFrJ0505yFMxFILb49IuBZf/uHpFnmoH9/dB2hwz9xCUiJMOwCeSMHjpsfw xCMjTsRxbHewQataFTFSYWe9jF2S+h8q0RkanI4geT+7rvnIobJbHrz5afjHnLqg2+Qnlk0atfZjI huZ7Z21+ZTQZAII+zfO43fjulwrzc3Twnm3z9DM8cb9sLG6YcOX6C1Y4Y91YNFeC6ffeAZ2Rl+lfk vB3tS8pg==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-2T for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error Date: Mon, 5 Jun 2023 20:17:28 +0100 Message-Id: <20230605191735.119210-2-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org When checking for waste, we check that the packet is at least eight bytes long and then examine the first nine bytes. Fix the length check. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index 2a9f3e4553b0..a90d1b3d57c8 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -793,7 +793,7 @@ search_xdcc(const unsigned char *payload, const unsigned int plen) static unsigned int search_waste(const unsigned char *payload, const unsigned int plen) { - if (plen >= 8 && memcmp(payload, "GET.sha1:", 9) == 0) + if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0) return IPP2P_WASTE * 100 + 0; return 0; From patchwork Mon Jun 5 19:17:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790623 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=GL+z/mIt; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk3N393sz20Vv for ; Tue, 6 Jun 2023 05:20:48 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231544AbjFETUq (ORCPT ); Mon, 5 Jun 2023 15:20:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235539AbjFETTv (ORCPT ); Mon, 5 Jun 2023 15:19:51 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D5331702 for ; Mon, 5 Jun 2023 12:19:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=nYuY1ihBvSji0HCIpSK5PJx4FHWv/wqhbesM3GboJGE=; b=GL+z/mItEEUSjxt8Fu78gQ5N3l RrHtVHOxCYkCWAAg2OEd1hgqXxmnZb66tyTG2mkRJLPlVIpeNxQsuDif0Iz4bU++4O32JaoEWxIX/ c4Afb5G0sro+gMQrlh2QYOZS6UkE4xQ9sbtzllW1DNp4shp92iwx7L0YSEKQHD4j54fT6qonjZeG2 l29i+ZZ5cCMZw9YoqX71up9ML1mJ71Or43Jt3dc5dsiUz5o7L3w60IZgMS4/FDvxUsxUOzBSsH6LO oY9k58k1KUdLkNLXSNFEnEclyZTIypr/KUgQmR/OlMaFq51EoKbMQRMMOiswogdk4h7fCOq2GP12f HNDgxZKw==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-48 for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 2/8] xt_ipp2p: fix Soulseek false-positive matches Date: Mon, 5 Jun 2023 20:17:29 +0100 Message-Id: <20230605191735.119210-3-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org According to the comment, the last match attempted is: 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 However, the conditional that inspects the last ten bytes is followed by a semi-colon, so the printk and return statements are executed regard- less of what the last ten bytes are. Remove the semi-colon and only execute the printk and return if the conditional expression is true. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index a90d1b3d57c8..5f7d5f61b96e 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -448,13 +448,13 @@ search_soul(const unsigned char *payload, const unsigned int plen) const unsigned char *w = payload + 9 + y; if (get_u32(w, 0) == 0x01 && (get_u16(w, 4) == 0x4600 || - get_u16(w, 4) == 0x5000) && - get_u32(w, 6) == 0x00) - ; + get_u16(w, 4) == 0x5000) && + get_u32(w, 6) == 0x00) { #ifdef IPP2P_DEBUG_SOUL - printk(KERN_DEBUG "Soulssek special client command recognized\n"); + printk(KERN_DEBUG "Soulseek special client command recognized\n"); #endif - return IPP2P_SOUL * 100 + 9; + return IPP2P_SOUL * 100 + 9; + } } } return 0; From patchwork Mon Jun 5 19:17:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790616 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=W6Xjbof9; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2q3kTvz20QH for ; Tue, 6 Jun 2023 05:20:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232171AbjFETUR (ORCPT ); Mon, 5 Jun 2023 15:20:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235760AbjFETTx (ORCPT ); Mon, 5 Jun 2023 15:19:53 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D2E271706 for ; Mon, 5 Jun 2023 12:19:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=FGBJWk09SxVYUOVSifnIcd9VrkGVyWS7kh9bnNpDVxQ=; b=W6Xjbof9dykaDkhFNfqknWdXB4 mfAXqNrIwSBmCgssRXITZp1jqmbAF+A4sG/QCHid0Tzl4G0zhfpSyFXQVewIN3Usat7SK8tEQYDfW XP/8H11SsuEaecJ5Q8bmVsBHyxl/PgUZ+6+sUMLqw2DNj6Xff0vuHh4jFGdnaVHw5xoTRpEF4Znbu M4V1TlpH6R6a3yiBPwwyrqxZkC5bDpy7HIESea1oZA1PC1T8K8lj1MEYm/bQsXE799ykDXQ2lAMjJ 55V5I2a73vAw+wP4fz+BXeLNUuYwp6kR1/0YA+7furzVPXmuseIFlm3OMLcywb3h8MrLkMogYVV9q bGBdgWzw==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-5l for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 3/8] xt_ipp2p: change byte-orer conversion Date: Mon, 5 Jun 2023 20:17:30 +0100 Message-Id: <20230605191735.119210-4-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Instead of converting the packet bytes before comparing it to a constant, convert the constant. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index 5f7d5f61b96e..4790c2fca229 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -210,8 +210,8 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len) switch (packet_len) { case 16: /* ^ 00 00 04 17 27 10 19 80 */ - if (ntohl(get_u32(haystack, 0)) == 0x00000417 && - ntohl(get_u32(haystack, 4)) == 0x27101980) + if (get_u32(haystack, 0) == __constant_htonl(0x00000417) && + get_u32(haystack, 4) == __constant_htonl(0x27101980)) return IPP2P_BIT * 100 + 50; break; case 36: From patchwork Mon Jun 5 19:17:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790617 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=c7lDdT3O; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2v2J6Hz20Vv for ; Tue, 6 Jun 2023 05:20:23 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231667AbjFETUR (ORCPT ); Mon, 5 Jun 2023 15:20:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41740 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235764AbjFETTy (ORCPT ); Mon, 5 Jun 2023 15:19:54 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6727B1707 for ; Mon, 5 Jun 2023 12:19:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=omlXSo3pq1a1PcVIZP1WDvDbcSGKVJkVzP/I3L7ULKc=; b=c7lDdT3OvpCWyBOzzrMFqanYd0 xSnml1HsynbCQ7uwqUnV6QA9K2LFGfxxljAIZLX2UkeozPvymA/KwNgktwVLw+vTvyj7AdQR2BAdi +gy3CqWroxbxqpXrm1x/lQVEv8CoNDx9M5OKecqmyf7HPAS0Lsc9WmusMb6BXwxz9qCeTGOfuBMVv DyRu90NXbsWXNRv9YtegCaDzHsWOJ6hxpXguEkgGEm2wEU+vlWy9YK3g8CW+15tNZ9n+nZrPibkfz U1qe1P/vOmGB6se6UWd0E42FF8TfyAfD30bGhSo/RCOJb8k22xH7luPsb8YXxciflhXqWN9at6laN q5sKoFGg==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-7N for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 4/8] xt_ipp2p: add helper for matching "\r\n" Date: Mon, 5 Jun 2023 20:17:31 +0100 Message-Id: <20230605191735.119210-5-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org There are repeated checks that: pkt[x] == 0x0d && pkt[x + 1] == 0x0a Replace them with `iscrlf(&pkt[x])` function calls. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index 4790c2fca229..de253c4f4cb4 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -39,6 +39,11 @@ struct ipp2p_result_printer { void (*print)(const union nf_inet_addr *, short, const union nf_inet_addr *, short, bool, unsigned int); }; +static bool iscrlf(const unsigned char *str) +{ + return *str == '\r' && *(str + 1) == '\n'; +} + static void print_result(const struct ipp2p_result_printer *rp, bool result, unsigned int hlen) @@ -518,7 +523,7 @@ search_winmx(const unsigned char *payload, const unsigned int plen) static unsigned int search_apple(const unsigned char *payload, const unsigned int plen) { - if (plen > 7 && payload[6] == 0x0d && payload[7] == 0x0a && + if (plen > 7 && iscrlf(&payload[6]) && memcmp(payload, "ajprot", 6) == 0) return IPP2P_APPLE * 100; @@ -574,7 +579,7 @@ search_kazaa(const unsigned char *payload, const unsigned int plen) { if (plen < 13) return 0; - if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a && + if (iscrlf(&payload[plen - 2]) && memcmp(payload, "GET /.hash=", 11) == 0) return IPP2P_DATA_KAZAA * 100; @@ -587,7 +592,7 @@ search_gnu(const unsigned char *payload, const unsigned int plen) { if (plen < 11) return 0; - if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) { + if (iscrlf(&payload[plen - 2])) { if (memcmp(payload, "GET /get/", 9) == 0) return IPP2P_DATA_GNU * 100 + 1; if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0) @@ -602,7 +607,7 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen) { if (plen < 11) return 0; - if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) { + if (iscrlf(&payload[plen - 2])) { if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return IPP2P_GNU * 100 + 1; if (memcmp(payload, "GNUTELLA/", 9) == 0) @@ -614,8 +619,7 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen) unsigned int c; for (c = 0; c < plen - 22; ++c) - if (payload[c] == 0x0d && - payload[c+1] == 0x0a && + if (iscrlf(&payload[c]) && (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0 || memcmp(&payload[c+2], "X-Queue:", 8) == 0)) return IPP2P_GNU * 100 + 3; @@ -635,7 +639,7 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen) /* too short for anything we test for - early bailout */ return 0; - if (payload[plen-2] != 0x0d || payload[plen-1] != 0x0a) + if (!iscrlf(&payload[plen - 2])) return 0; if (memcmp(payload, "GIVE ", 5) == 0) @@ -651,9 +655,7 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen) end = plen - 18; rem = plen - 5; for (c = 5; c < end; ++c, --rem) { - if (payload[c] != 0x0d) - continue; - if (payload[c+1] != 0x0a) + if (!iscrlf(&payload[c])) continue; if (rem >= 18 && memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) @@ -769,8 +771,8 @@ static unsigned int search_xdcc(const unsigned char *payload, const unsigned int plen) { /* search in small packets only */ - if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && - payload[plen-2] == 0x0d && memcmp(payload, "PRIVMSG ", 8) == 0) + if (plen > 20 && plen < 200 && iscrlf(&payload[plen - 2]) && + memcmp(payload, "PRIVMSG ", 8) == 0) { uint16_t x = 10; const uint16_t end = plen - 13; From patchwork Mon Jun 5 19:17:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790621 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=MEGBdivV; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2w6KVPz20Vv for ; Tue, 6 Jun 2023 05:20:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235392AbjFETUT (ORCPT ); Mon, 5 Jun 2023 15:20:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40946 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235787AbjFETT5 (ORCPT ); Mon, 5 Jun 2023 15:19:57 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F4111708 for ; Mon, 5 Jun 2023 12:19:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=8cIxP02I6Y/JhU8MUgjYL5Rl75iOlhh0vPK83feuoAw=; b=MEGBdivVUVYbF7nZfG0ZHLidj6 IgiGAL7nZeAItjK2hOuCbzmiKukDgummyqFgaHp/f5T2nnajz/sqDvRDn8nY50OjwYwpRZ5U6vLnR uYasn6/F3eV4qmxuD6Uno0kH0p4Z7BFgL7YZvNiMT9tlkhoBpcf4YXf9kliwZvS8OuTdlWNEeO03q wLzc0ueh4it+chXu3Dzcz0/ssv4UjnSGvfrnTViH0dMWD7I8FTg12M7AbRU3qXOS55BYEHqJxF6JW qwlzgqBDXv2so4C8n9HdSy/P/XLcedCKCVQ31BVfu65RuMqgH1es1Ut5omB2kCTATVg2wkvj+q8Zi e8vgn7uQ==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-98 for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops Date: Mon, 5 Jun 2023 20:17:32 +0100 Message-Id: <20230605191735.119210-6-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Reduce indentation and improve the readability of the code. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 333 ++++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 161 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index de253c4f4cb4..ae9a3dd2a920 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -199,12 +199,14 @@ static unsigned int udp_search_directconnect(const unsigned char *t, { if (packet_len < 5) return 0; - if (t[0] == 0x24 && t[packet_len-1] == 0x7c) { - if (memcmp(&t[1], "SR ", 3) == 0) - return IPP2P_DC * 100 + 60; - if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0) - return IPP2P_DC * 100 + 61; - } + if (t[0] != 0x24) + return 0; + if (t[packet_len-1] != 0x7c) + return 0; + if (memcmp(&t[1], "SR ", 3) == 0) + return IPP2P_DC * 100 + 60; + if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0) + return IPP2P_DC * 100 + 61; return 0; } @@ -263,12 +265,14 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len) } /* some extra-bitcomet rules: "d1:" [a|r] "d2:id20:" */ - if (packet_len > 22 && get_u8(haystack, 0) == 'd' && - get_u8(haystack, 1) == '1' && get_u8(haystack, 2) == ':') - if (get_u8(haystack, 3) == 'a' || - get_u8(haystack, 3) == 'r') - if (memcmp(haystack + 4, "d2:id20:", 8) == 0) - return IPP2P_BIT * 100 + 57; + if (packet_len > 22 && + get_u8(haystack, 0) == 'd' && + get_u8(haystack, 1) == '1' && + get_u8(haystack, 2) == ':' && + (get_u8(haystack, 3) == 'a' || + get_u8(haystack, 3) == 'r') && + memcmp(haystack + 4, "d2:id20:", 8) == 0) + return IPP2P_BIT * 100 + 57; #if 0 /* bitlord rules */ @@ -447,19 +451,22 @@ search_soul(const unsigned char *payload, const unsigned int plen) /* without size at the beginning !!! */ if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) { uint32_t y = get_u32(payload, 5); + const unsigned char *w; /* we need 19 chars + string */ - if (y + 19 <= plen) { - const unsigned char *w = payload + 9 + y; - if (get_u32(w, 0) == 0x01 && - (get_u16(w, 4) == 0x4600 || - get_u16(w, 4) == 0x5000) && - get_u32(w, 6) == 0x00) { + if (plen < y + 19) + return 0; + + w = payload + 9 + y; + + if (get_u32(w, 0) == 0x01 && + (get_u16(w, 4) == 0x4600 || + get_u16(w, 4) == 0x5000) && + get_u32(w, 6) == 0x00) { #ifdef IPP2P_DEBUG_SOUL - printk(KERN_DEBUG "Soulseek special client command recognized\n"); + printk(KERN_DEBUG "Soulseek special client command recognized\n"); #endif - return IPP2P_SOUL * 100 + 9; - } + return IPP2P_SOUL * 100 + 9; } } return 0; @@ -523,10 +530,10 @@ search_winmx(const unsigned char *payload, const unsigned int plen) static unsigned int search_apple(const unsigned char *payload, const unsigned int plen) { - if (plen > 7 && iscrlf(&payload[6]) && - memcmp(payload, "ajprot", 6) == 0) + if (plen < 8) + return 0; + if (memcmp(payload, "ajprot\r\n", 8) == 0) return IPP2P_APPLE * 100; - return 0; } @@ -534,41 +541,38 @@ search_apple(const unsigned char *payload, const unsigned int plen) static unsigned int search_bittorrent(const unsigned char *payload, const unsigned int plen) { - if (plen > 20) { - /* test for match 0x13+"BitTorrent protocol" */ - if (payload[0] == 0x13) - if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0) - return IPP2P_BIT * 100; - /* - * Any tracker command starts with GET / then *may be* some file on web server - * (e.g. announce.php or dupa.pl or whatever.cgi or NOTHING for tracker on root dir) - * but *must have* one (or more) of strings listed below (true for scrape and announce) - */ - if (memcmp(payload, "GET /", 5) == 0) { - if (HX_memmem(payload, plen, "info_hash=", 10) != NULL) - return IPP2P_BIT * 100 + 1; - if (HX_memmem(payload, plen, "peer_id=", 8) != NULL) - return IPP2P_BIT * 100 + 2; - if (HX_memmem(payload, plen, "passkey=", 8) != NULL) - return IPP2P_BIT * 100 + 4; - } - } else { - /* bitcomet encryptes the first packet, so we have to detect another - * one later in the flow */ - /* first try failed, too many false positives */ - /* - if (size == 5 && get_u32(t, 0) == __constant_htonl(1) && - t[4] < 3) - return IPP2P_BIT * 100 + 3; - */ + /* + * bitcomet encrypts the first packet, so we have to detect another one + * later in the flow. + */ + if (plen == 17 && + get_u32(payload, 0) == __constant_htonl(0x0d) && + payload[4] == 0x06 && + get_u32(payload,13) == __constant_htonl(0x4000)) + return IPP2P_BIT * 100 + 3; - /* second try: block request packets */ - if (plen == 17 && - get_u32(payload, 0) == __constant_htonl(0x0d) && - payload[4] == 0x06 && - get_u32(payload,13) == __constant_htonl(0x4000)) - return IPP2P_BIT * 100 + 3; - } + if (plen <= 20) + return 0; + + /* test for match 0x13+"BitTorrent protocol" */ + if (payload[0] == 0x13) + if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0) + return IPP2P_BIT * 100; + + /* + * Any tracker command starts with GET / then *may be* some file + * on web server (e.g. announce.php or dupa.pl or whatever.cgi + * or NOTHING for tracker on root dir) but *must have* one (or + * more) of strings listed below (true for scrape and announce) + */ + if (memcmp(payload, "GET /", 5) != 0) + return 0; + if (HX_memmem(payload, plen, "info_hash=", 10) != NULL) + return IPP2P_BIT * 100 + 1; + if (HX_memmem(payload, plen, "peer_id=", 8) != NULL) + return IPP2P_BIT * 100 + 2; + if (HX_memmem(payload, plen, "passkey=", 8) != NULL) + return IPP2P_BIT * 100 + 4; return 0; } @@ -592,12 +596,12 @@ search_gnu(const unsigned char *payload, const unsigned int plen) { if (plen < 11) return 0; - if (iscrlf(&payload[plen - 2])) { - if (memcmp(payload, "GET /get/", 9) == 0) - return IPP2P_DATA_GNU * 100 + 1; - if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0) - return IPP2P_DATA_GNU * 100 + 2; - } + if (!iscrlf(&payload[plen - 2])) + return 0; + if (memcmp(payload, "GET /get/", 9) == 0) + return IPP2P_DATA_GNU * 100 + 1; + if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0) + return IPP2P_DATA_GNU * 100 + 2; return 0; } @@ -605,25 +609,33 @@ search_gnu(const unsigned char *payload, const unsigned int plen) static unsigned int search_all_gnu(const unsigned char *payload, const unsigned int plen) { + unsigned int c; + if (plen < 11) return 0; - if (iscrlf(&payload[plen - 2])) { - if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) - return IPP2P_GNU * 100 + 1; - if (memcmp(payload, "GNUTELLA/", 9) == 0) - return IPP2P_GNU * 100 + 2; - - if (plen >= 22 && (memcmp(payload, "GET /get/", 9) == 0 || - memcmp(payload, "GET /uri-res/", 13) == 0)) - { - unsigned int c; + if (!iscrlf(&payload[plen - 2])) + return 0; + if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) + return IPP2P_GNU * 100 + 1; + if (memcmp(payload, "GNUTELLA/", 9) == 0) + return IPP2P_GNU * 100 + 2; - for (c = 0; c < plen - 22; ++c) - if (iscrlf(&payload[c]) && - (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0 || - memcmp(&payload[c+2], "X-Queue:", 8) == 0)) - return IPP2P_GNU * 100 + 3; - } + if (plen < 22) + return 0; + + if (memcmp(payload, "GET /get/", 9) != 0 && + memcmp(payload, "GET /uri-res/", 13) != 0) + return 0; + + for (c = 0; c < plen - 22; ++c) { + if (!iscrlf(&payload[c])) + continue; + + if (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) + return IPP2P_GNU * 100 + 3; + + if ( memcmp(&payload[c+2], "X-Queue:", 8) == 0) + return IPP2P_GNU * 100 + 3; } return 0; } @@ -674,39 +686,37 @@ search_edk(const unsigned char *payload, const unsigned int plen) { if (plen < 6) return 0; - if (payload[0] != 0xe3) { + if (payload[0] != 0xe3) return 0; - } else { - if (payload[5] == 0x47) - return IPP2P_DATA_EDK * 100; - else - return 0; - } + if (payload[5] == 0x47) + return IPP2P_DATA_EDK * 100; + return 0; } /* intensive but slower search for some edonkey packets including size-check */ static unsigned int search_all_edk(const unsigned char *payload, const unsigned int plen) { + unsigned int cmd; + if (plen < 6) return 0; - if (payload[0] != 0xe3) { + if (payload[0] != 0xe3) return 0; - } else { - unsigned int cmd = get_u16(payload, 1); - if (cmd == plen - 5) { - switch (payload[5]) { - case 0x01: - /* Client: hello or Server:hello */ + cmd = get_u16(payload, 1); + + if (cmd == plen - 5) { + switch (payload[5]) { + case 0x01: + /* Client: hello or Server:hello */ return IPP2P_EDK * 100 + 1; - case 0x4c: - /* Client: Hello-Answer */ - return IPP2P_EDK * 100 + 9; - } + case 0x4c: + /* Client: Hello-Answer */ + return IPP2P_EDK * 100 + 9; } - return 0; } + return 0; } /* fast check for Direct Connect send command */ @@ -715,36 +725,41 @@ search_dc(const unsigned char *payload, const unsigned int plen) { if (plen < 6) return 0; - if (payload[0] != 0x24) { + if (payload[0] != 0x24) return 0; - } else { - if (memcmp(&payload[1], "Send|", 5) == 0) - return IPP2P_DATA_DC * 100; - else - return 0; - } + if (memcmp(&payload[1], "Send|", 5) == 0) + return IPP2P_DATA_DC * 100; + return 0; } /* intensive but slower check for all direct connect packets */ static unsigned int search_all_dc(const unsigned char *payload, const unsigned int plen) { + const unsigned char *t; + if (plen < 7) return 0; - if (payload[0] == 0x24 && payload[plen-1] == 0x7c) { - const unsigned char *t = &payload[1]; - /* Client-Hub-Protocol */ - if (memcmp(t, "Lock ", 5) == 0) - return IPP2P_DC * 100 + 1; + if (payload[0] != 0x24) + return 0; + + if (payload[plen-1] != 0x7c) + return 0; + + t = &payload[1]; + + /* Client-Hub-Protocol */ + if (memcmp(t, "Lock ", 5) == 0) + return IPP2P_DC * 100 + 1; + + /* + * Client-Client-Protocol, some are already recognized by client-hub + * (like lock) + */ + if (plen >= 9 && memcmp(t, "MyNick ", 7) == 0) + return IPP2P_DC * 100 + 38; - /* - * Client-Client-Protocol, some are already recognized by - * client-hub (like lock) - */ - if (plen >= 9 && memcmp(t, "MyNick ", 7) == 0) - return IPP2P_DC * 100 + 38; - } return 0; } @@ -770,23 +785,25 @@ search_mute(const unsigned char *payload, const unsigned int plen) static unsigned int search_xdcc(const unsigned char *payload, const unsigned int plen) { + uint16_t x = 10; + const uint16_t end = plen - 13; + /* search in small packets only */ - if (plen > 20 && plen < 200 && iscrlf(&payload[plen - 2]) && - memcmp(payload, "PRIVMSG ", 8) == 0) - { - uint16_t x = 10; - const uint16_t end = plen - 13; + if (plen <= 20 || plen >= 200) + return 0; - /* - * is seems to be a irc private massage, chedck for - * xdcc command - */ - while (x < end) { - if (payload[x] == ':') - if (memcmp(&payload[x+1], "xdcc send #", 11) == 0) - return IPP2P_XDCC * 100 + 0; - x++; - } + if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2])) + return 0; + + /* + * is seems to be a irc private massage, chedck for + * xdcc command + */ + while (x < end) { + if (payload[x] == ':' && + memcmp(&payload[x + 1], "xdcc send #", 11) == 0) + return IPP2P_XDCC * 100 + 0; + x++; } return 0; } @@ -862,8 +879,7 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph, const struct ipp2p_result_printer *rp) { size_t tcph_len = tcph->doff * 4; - bool p2p_result = false; - int i = 0; + int i; if (tcph->fin) return 0; /* if FIN bit is set bail out */ if (tcph->syn) return 0; /* if SYN bit is set bail out */ @@ -880,20 +896,18 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph, haystack += tcph_len; hlen -= tcph_len; - while (matchlist[i].command) { - if ((info->cmd & matchlist[i].command) == matchlist[i].command && - hlen > matchlist[i].packet_len) - { - p2p_result = matchlist[i].function_name(haystack, hlen); - if (p2p_result) { - if (info->debug) - print_result(rp, p2p_result, hlen); - return p2p_result; - } + for (i = 0; matchlist[i].command; ++i) { + if ((info->cmd & matchlist[i].command) != matchlist[i].command) + continue; + if (hlen <= matchlist[i].packet_len) + continue; + if (matchlist[i].function_name(haystack, hlen)) { + if (info->debug) + print_result(rp, true, hlen); + return true; } - i++; } - return p2p_result; + return false; } static void @@ -920,8 +934,7 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph, const struct ipp2p_result_printer *rp) { size_t udph_len = sizeof(*udph); - bool p2p_result = false; - int i = 0; + int i; if (hlen < udph_len) { if (info->debug) @@ -934,20 +947,18 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph, haystack += udph_len; hlen -= udph_len; - while (udp_list[i].command) { - if ((info->cmd & udp_list[i].command) == udp_list[i].command && - hlen > udp_list[i].packet_len) - { - p2p_result = udp_list[i].function_name(haystack, hlen); - if (p2p_result) { - if (info->debug) - print_result(rp, p2p_result, hlen); - return p2p_result; - } + for (i = 0; udp_list[i].command; ++i) { + if ((info->cmd & udp_list[i].command) != udp_list[i].command) + continue; + if (hlen <= udp_list[i].packet_len) + continue; + if (udp_list[i].function_name(haystack, hlen)) { + if (info->debug) + print_result(rp, true, hlen); + return true; } - i++; } - return p2p_result; + return false; } static bool From patchwork Mon Jun 5 19:17:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790625 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=HNxJTuZS; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk3Q2dGcz20QH for ; Tue, 6 Jun 2023 05:20:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232353AbjFETUs (ORCPT ); Mon, 5 Jun 2023 15:20:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235801AbjFETUA (ORCPT ); Mon, 5 Jun 2023 15:20:00 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87C181709 for ; Mon, 5 Jun 2023 12:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Qq3/KVxbeCGcAIcy4c9zmqmbPDZWXYx5/1f0cUEOzeE=; b=HNxJTuZST0RXgfiwuH9IYQCSJ8 mG8COB27CYe30rcet4aPCkR0SK5/h/qsVXHjtyqmFoi9ltxe8N2k86XIsiqYOjlP7vySXPZyqenh+ Rx4ff0LeSxQggQJC5+hwGvKKTBqqEdKsUslbi9cmAN4jfsQPvh/lkJsbwX0d4FFdNDN5U7MM5xZEc mumxe4owbBRnRxRESVht48dae/zCTJE43UvwhoVp4rI0mcBjw95VKJP/IkcJ1TFutr9xjDhOzS7J0 LEmaMVs6je6nXEHyr4ktF3gikbL1pLlf6Kye/HD9RFHpnVyuJYnwCnRAmPPUecDIcWysYYAlfuKPo S5WvrWGg==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-B0 for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 6/8] xt_ipp2p: use textsearch API for substring searching Date: Mon, 5 Jun 2023 20:17:33 +0100 Message-Id: <20230605191735.119210-7-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Some of the matchers have hand-rolled substring search implementations. Replace them with the kernel's textsearch API. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 312 +++++++++++++++++++++++++++++++----------- extensions/xt_ipp2p.h | 10 ++ 2 files changed, 245 insertions(+), 77 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index ae9a3dd2a920..1378701605c3 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include @@ -55,7 +57,8 @@ print_result(const struct ipp2p_result_printer *rp, bool result, /* Search for UDP eDonkey/eMule/Kad commands */ static unsigned int -udp_search_edk(const unsigned char *t, const unsigned int packet_len) +udp_search_edk(const unsigned char *t, const unsigned int packet_len, + const struct ipt_p2p_info *info) { if (packet_len < 4) return 0; @@ -173,7 +176,8 @@ udp_search_edk(const unsigned char *t, const unsigned int packet_len) /* Search for UDP Gnutella commands */ static unsigned int -udp_search_gnu(const unsigned char *t, const unsigned int packet_len) +udp_search_gnu(const unsigned char *t, const unsigned int packet_len, + const struct ipt_p2p_info *info) { if (packet_len >= 3 && memcmp(t, "GND", 3) == 0) return IPP2P_GNU * 100 + 51; @@ -184,7 +188,8 @@ udp_search_gnu(const unsigned char *t, const unsigned int packet_len) /* Search for UDP KaZaA commands */ static unsigned int -udp_search_kazaa(const unsigned char *t, const unsigned int packet_len) +udp_search_kazaa(const unsigned char *t, const unsigned int packet_len, + const struct ipt_p2p_info *info) { if (packet_len < 6) return 0; @@ -194,8 +199,9 @@ udp_search_kazaa(const unsigned char *t, const unsigned int packet_len) } /* Search for UDP DirectConnect commands */ -static unsigned int udp_search_directconnect(const unsigned char *t, - const unsigned int packet_len) +static unsigned int +udp_search_directconnect(const unsigned char *t, const unsigned int packet_len, + const struct ipt_p2p_info *info) { if (packet_len < 5) return 0; @@ -212,7 +218,8 @@ static unsigned int udp_search_directconnect(const unsigned char *t, /* Search for UDP BitTorrent commands */ static unsigned int -udp_search_bit(const unsigned char *haystack, const unsigned int packet_len) +udp_search_bit(const unsigned char *haystack, const unsigned int packet_len, + const struct ipt_p2p_info *info) { switch (packet_len) { case 16: @@ -298,7 +305,8 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len) /* Search for Ares commands */ static unsigned int -search_ares(const unsigned char *payload, const unsigned int plen) +search_ares(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 3) return 0; @@ -350,7 +358,8 @@ search_ares(const unsigned char *payload, const unsigned int plen) /* Search for SoulSeek commands */ static unsigned int -search_soul(const unsigned char *payload, const unsigned int plen) +search_soul(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 8) return 0; @@ -474,8 +483,11 @@ search_soul(const unsigned char *payload, const unsigned int plen) /* Search for WinMX commands */ static unsigned int -search_winmx(const unsigned char *payload, const unsigned int plen) +search_winmx(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { + uint16_t start; + if (plen == 4 && memcmp(payload, "SEND", 4) == 0) return IPP2P_WINMX * 100 + 1; if (plen == 3 && memcmp(payload, "GET", 3) == 0) @@ -487,20 +499,33 @@ search_winmx(const unsigned char *payload, const unsigned int plen) if (plen < 10) return 0; - if (memcmp(payload, "SEND", 4) == 0 || memcmp(payload, "GET", 3) == 0) { - uint16_t c = 4; - const uint16_t end = plen - 2; + if (memcmp(payload, "SEND", 4) == 0) + start = 4; + else if (memcmp(payload, "GET", 3) == 0) + start = 3; + else + start = 0; + + if (start) { uint8_t count = 0; - while (c < end) { - if (payload[c] == 0x20 && payload[c+1] == 0x22) { - c++; - count++; - if (count >= 2) - return IPP2P_WINMX * 100 + 3; - } - c++; - } + do { + struct ts_state state; + unsigned int pos; + + pos = textsearch_find_continuous(info->ts_conf_winmx, + &state, + &payload[start], + plen - start); + if (pos == UINT_MAX) + break; + + count++; + if (count >= 2) + return IPP2P_WINMX * 100 + 3; + + start = pos + 2; + } while (start < plen); } if (plen == 149 && payload[0] == '8') { @@ -528,7 +553,8 @@ search_winmx(const unsigned char *payload, const unsigned int plen) /* Search for appleJuice commands */ static unsigned int -search_apple(const unsigned char *payload, const unsigned int plen) +search_apple(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 8) return 0; @@ -539,8 +565,12 @@ search_apple(const unsigned char *payload, const unsigned int plen) /* Search for BitTorrent commands */ static unsigned int -search_bittorrent(const unsigned char *payload, const unsigned int plen) +search_bittorrent(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { + struct ts_state state; + unsigned int pos; + /* * bitcomet encrypts the first packet, so we have to detect another one * later in the flow. @@ -567,11 +597,20 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen) */ if (memcmp(payload, "GET /", 5) != 0) return 0; - if (HX_memmem(payload, plen, "info_hash=", 10) != NULL) + + pos = textsearch_find_continuous(info->ts_conf_bt_info_hash, + &state, &payload[5], plen - 5); + if (pos != UINT_MAX) return IPP2P_BIT * 100 + 1; - if (HX_memmem(payload, plen, "peer_id=", 8) != NULL) + + pos = textsearch_find_continuous(info->ts_conf_bt_peer_id, + &state, &payload[5], plen - 5); + if (pos != UINT_MAX) return IPP2P_BIT * 100 + 2; - if (HX_memmem(payload, plen, "passkey=", 8) != NULL) + + pos = textsearch_find_continuous(info->ts_conf_bt_passkey, + &state, &payload[5], plen - 5); + if (pos != UINT_MAX) return IPP2P_BIT * 100 + 4; return 0; @@ -579,7 +618,8 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen) /* check for Kazaa get command */ static unsigned int -search_kazaa(const unsigned char *payload, const unsigned int plen) +search_kazaa(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 13) return 0; @@ -592,7 +632,8 @@ search_kazaa(const unsigned char *payload, const unsigned int plen) /* check for gnutella get command */ static unsigned int -search_gnu(const unsigned char *payload, const unsigned int plen) +search_gnu(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 11) return 0; @@ -607,9 +648,11 @@ search_gnu(const unsigned char *payload, const unsigned int plen) /* check for gnutella get commands and other typical data */ static unsigned int -search_all_gnu(const unsigned char *payload, const unsigned int plen) +search_all_gnu(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { - unsigned int c; + struct ts_state state; + unsigned int c, pos; if (plen < 11) return 0; @@ -623,29 +666,34 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen) if (plen < 22) return 0; - if (memcmp(payload, "GET /get/", 9) != 0 && - memcmp(payload, "GET /uri-res/", 13) != 0) + if (memcmp(payload, "GET /get/", 9) == 0) + c = 9; + else if (memcmp(payload, "GET /uri-res/", 13) == 0) + c = 13; + else return 0; - for (c = 0; c < plen - 22; ++c) { - if (!iscrlf(&payload[c])) - continue; + pos = textsearch_find_continuous(info->ts_conf_gnu_x_gnutella, + &state, &payload[c], plen - c); + if (pos != UINT_MAX) + return IPP2P_GNU * 100 + 3; - if (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) - return IPP2P_GNU * 100 + 3; + pos = textsearch_find_continuous(info->ts_conf_gnu_x_queue, + &state, &payload[c], plen - c); + if (pos != UINT_MAX) + return IPP2P_GNU * 100 + 3; - if ( memcmp(&payload[c+2], "X-Queue:", 8) == 0) - return IPP2P_GNU * 100 + 3; - } return 0; } /* check for KaZaA download commands and other typical data */ /* plen is guaranteed to be >= 5 (see @matchlist) */ static unsigned int -search_all_kazaa(const unsigned char *payload, const unsigned int plen) +search_all_kazaa(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { - uint16_t c, end, rem; + struct ts_state state; + unsigned int pos; if (plen < 7) /* too short for anything we test for - early bailout */ @@ -664,25 +712,23 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen) /* The next tests would not succeed anyhow. */ return 0; - end = plen - 18; - rem = plen - 5; - for (c = 5; c < end; ++c, --rem) { - if (!iscrlf(&payload[c])) - continue; - if (rem >= 18 && - memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) - return IPP2P_KAZAA * 100 + 2; - if (rem >= 24 && - memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0) - return IPP2P_KAZAA * 100 + 2; - } + pos = textsearch_find_continuous(info->ts_conf_kz_x_kazaa_username, + &state, &payload[5], plen - 5); + if (pos != UINT_MAX) + return IPP2P_KAZAA * 100 + 2; + + pos = textsearch_find_continuous(info->ts_conf_kz_user_agent, + &state, &payload[5], plen - 5); + if (pos != UINT_MAX) + return IPP2P_KAZAA * 100 + 2; return 0; } /* fast check for edonkey file segment transfer command */ static unsigned int -search_edk(const unsigned char *payload, const unsigned int plen) +search_edk(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 6) return 0; @@ -695,7 +741,8 @@ search_edk(const unsigned char *payload, const unsigned int plen) /* intensive but slower search for some edonkey packets including size-check */ static unsigned int -search_all_edk(const unsigned char *payload, const unsigned int plen) +search_all_edk(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { unsigned int cmd; @@ -721,7 +768,8 @@ search_all_edk(const unsigned char *payload, const unsigned int plen) /* fast check for Direct Connect send command */ static unsigned int -search_dc(const unsigned char *payload, const unsigned int plen) +search_dc(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen < 6) return 0; @@ -734,7 +782,8 @@ search_dc(const unsigned char *payload, const unsigned int plen) /* intensive but slower check for all direct connect packets */ static unsigned int -search_all_dc(const unsigned char *payload, const unsigned int plen) +search_all_dc(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { const unsigned char *t; @@ -765,7 +814,8 @@ search_all_dc(const unsigned char *payload, const unsigned int plen) /* check for mute */ static unsigned int -search_mute(const unsigned char *payload, const unsigned int plen) +search_mute(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121) { @@ -783,10 +833,11 @@ search_mute(const unsigned char *payload, const unsigned int plen) /* check for xdcc */ static unsigned int -search_xdcc(const unsigned char *payload, const unsigned int plen) +search_xdcc(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { - uint16_t x = 10; - const uint16_t end = plen - 13; + struct ts_state state; + unsigned int pos; /* search in small packets only */ if (plen <= 20 || plen >= 200) @@ -795,22 +846,19 @@ search_xdcc(const unsigned char *payload, const unsigned int plen) if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2])) return 0; - /* - * is seems to be a irc private massage, chedck for - * xdcc command - */ - while (x < end) { - if (payload[x] == ':' && - memcmp(&payload[x + 1], "xdcc send #", 11) == 0) - return IPP2P_XDCC * 100 + 0; - x++; - } + /* seems to be a irc private massage, check for xdcc command */ + pos = textsearch_find_continuous(info->ts_conf_xdcc, + &state, &payload[8], plen - 8); + if (pos != UINT_MAX) + return IPP2P_XDCC * 100 + 0; + return 0; } /* search for waste */ static unsigned int -search_waste(const unsigned char *payload, const unsigned int plen) +search_waste(const unsigned char *payload, const unsigned int plen, + const struct ipt_p2p_info *info) { if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0) return IPP2P_WASTE * 100 + 0; @@ -821,7 +869,8 @@ search_waste(const unsigned char *payload, const unsigned int plen) static const struct { unsigned int command; unsigned int packet_len; - unsigned int (*function_name)(const unsigned char *, const unsigned int); + unsigned int (*function_name)(const unsigned char *, const unsigned int, + const struct ipt_p2p_info *); } matchlist[] = { {IPP2P_EDK, 20, search_all_edk}, {IPP2P_DATA_KAZAA, 200, search_kazaa}, /* exp */ @@ -845,7 +894,8 @@ static const struct { static const struct { unsigned int command; unsigned int packet_len; - unsigned int (*function_name)(const unsigned char *, const unsigned int); + unsigned int (*function_name)(const unsigned char *, const unsigned int, + const struct ipt_p2p_info *); } udp_list[] = { {IPP2P_KAZAA, 14, udp_search_kazaa}, {IPP2P_BIT, 23, udp_search_bit}, @@ -901,7 +951,7 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph, continue; if (hlen <= matchlist[i].packet_len) continue; - if (matchlist[i].function_name(haystack, hlen)) { + if (matchlist[i].function_name(haystack, hlen, info)) { if (info->debug) print_result(rp, true, hlen); return true; @@ -952,7 +1002,7 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph, continue; if (hlen <= udp_list[i].packet_len) continue; - if (udp_list[i].function_name(haystack, hlen)) { + if (udp_list[i].function_name(haystack, hlen, info)) { if (info->debug) print_result(rp, true, hlen); return true; @@ -1041,12 +1091,118 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par) } } +static int ipp2p_mt_check(const struct xt_mtchk_param *par) +{ + struct ipt_p2p_info *info = par->matchinfo; + struct ts_config *ts_conf; + + ts_conf = textsearch_prepare("bm", "\x20\x22", 2, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_return; + info->ts_conf_winmx = ts_conf; + + ts_conf = textsearch_prepare("bm", "info_hash=", 10, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_winmx; + info->ts_conf_bt_info_hash = ts_conf; + + ts_conf = textsearch_prepare("bm", "peer_id=", 8, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_bt_info_hash; + info->ts_conf_bt_peer_id = ts_conf; + + ts_conf = textsearch_prepare("bm", "passkey", 8, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_bt_peer_id; + info->ts_conf_bt_passkey = ts_conf; + + ts_conf = textsearch_prepare("bm", "\r\nX-Gnutella-", 13, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_bt_passkey; + info->ts_conf_gnu_x_gnutella = ts_conf; + + ts_conf = textsearch_prepare("bm", "\r\nX-Queue-", 10, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_gnu_x_gnutella; + info->ts_conf_gnu_x_queue = ts_conf; + + ts_conf = textsearch_prepare("bm", "\r\nX-Kazaa-Username: ", 20, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_gnu_x_queue; + info->ts_conf_kz_x_kazaa_username = ts_conf; + + ts_conf = textsearch_prepare("bm", "\r\nUser-Agent: PeerEnabler/", 26, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_kazaa_x_kazaa_username; + info->ts_conf_kz_user_agent = ts_conf; + + ts_conf = textsearch_prepare("bm", ":xdcc send #", 12, + GFP_KERNEL, TS_AUTOLOAD); + if (IS_ERR(ts_conf)) + goto err_ts_destroy_kazaa_user_agent; + info->ts_conf_xdcc = ts_conf; + + return 0; + +err_ts_destroy_kazaa_user_agent: + textsearch_destroy(info->ts_conf_kz_user_agent); + +err_ts_destroy_kazaa_x_kazaa_username: + textsearch_destroy(info->ts_conf_kz_x_kazaa_username); + +err_ts_destroy_gnu_x_queue: + textsearch_destroy(info->ts_conf_gnu_x_queue); + +err_ts_destroy_gnu_x_gnutella: + textsearch_destroy(info->ts_conf_gnu_x_gnutella); + +err_ts_destroy_bt_passkey: + textsearch_destroy(info->ts_conf_bt_passkey); + +err_ts_destroy_bt_peer_id: + textsearch_destroy(info->ts_conf_bt_peer_id); + +err_ts_destroy_bt_info_hash: + textsearch_destroy(info->ts_conf_bt_info_hash); + +err_ts_destroy_winmx: + textsearch_destroy(info->ts_conf_winmx); + +err_return: + return PTR_ERR(ts_conf); +} + +static void ipp2p_mt_destroy(const struct xt_mtdtor_param *par) +{ + struct ipt_p2p_info *info = (struct ipt_p2p_info *) par->matchinfo; + + textsearch_destroy(info->ts_conf_winmx); + textsearch_destroy(info->ts_conf_bt_info_hash); + textsearch_destroy(info->ts_conf_bt_peer_id); + textsearch_destroy(info->ts_conf_bt_passkey); + textsearch_destroy(info->ts_conf_gnu_x_gnutella); + textsearch_destroy(info->ts_conf_gnu_x_queue); + textsearch_destroy(info->ts_conf_kz_x_kazaa_username); + textsearch_destroy(info->ts_conf_kz_user_agent); + textsearch_destroy(info->ts_conf_xdcc); +} + static struct xt_match ipp2p_mt_reg[] __read_mostly = { { .name = "ipp2p", .revision = 1, .family = NFPROTO_IPV4, + .checkentry = ipp2p_mt_check, .match = ipp2p_mt, + .destroy = ipp2p_mt_destroy, .matchsize = sizeof(struct ipt_p2p_info), .me = THIS_MODULE, }, @@ -1054,7 +1210,9 @@ static struct xt_match ipp2p_mt_reg[] __read_mostly = { .name = "ipp2p", .revision = 1, .family = NFPROTO_IPV6, + .checkentry = ipp2p_mt_check, .match = ipp2p_mt, + .destroy = ipp2p_mt_destroy, .matchsize = sizeof(struct ipt_p2p_info), .me = THIS_MODULE, }, diff --git a/extensions/xt_ipp2p.h b/extensions/xt_ipp2p.h index f463f7f6e630..b821d75220b6 100644 --- a/extensions/xt_ipp2p.h +++ b/extensions/xt_ipp2p.h @@ -39,4 +39,14 @@ enum { struct ipt_p2p_info { int32_t cmd, debug; + + struct ts_config *ts_conf_winmx; + struct ts_config *ts_conf_bt_info_hash; + struct ts_config *ts_conf_bt_peer_id; + struct ts_config *ts_conf_bt_passkey; + struct ts_config *ts_conf_gnu_x_gnutella; + struct ts_config *ts_conf_gnu_x_queue; + struct ts_config *ts_conf_kz_x_kazaa_username; + struct ts_config *ts_conf_kz_user_agent; + struct ts_config *ts_conf_xdcc; }; From patchwork Mon Jun 5 19:17:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790619 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=eD8eGibi; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2w1dGfz20fG for ; Tue, 6 Jun 2023 05:20:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233779AbjFETUS (ORCPT ); Mon, 5 Jun 2023 15:20:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43762 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235789AbjFETT5 (ORCPT ); Mon, 5 Jun 2023 15:19:57 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 944B1170B for ; Mon, 5 Jun 2023 12:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=X1PLO31cYd1ePLbxVr66A+uIeB2VQYBsFpxqtS5/6hQ=; b=eD8eGibizk3fGZ8AdfE1oavSsn d2RUnlh2vpgAgRXuBt3SnXhwY+pNuAasayNH4mdM3bAbSghYBpIPjXSZWoxR899wyVg9av7SPzslX dE7DnVRTBHDjG58/xYXbycuxdcxSA/uHriMfDcKOQ9UUsDbd9x6MkGOmeMEmcKwhkuAwM2k0lXppF XtX0RC5byiON5NLtiEU6jZ/vOB/FlxUBQ+N4qXlIRBJDRoKMh9Q2pGOMbFWyUJQd2H+U9phQsbPSm hw//qnV31DHTJ790P4lMkSUeNoyl7JZMUnk5M2yQ53UAoZ8pY/Yibm2DmxK24inaUVC4xFi5p4R+2 lu08lxFw==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-D0 for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 7/8] xt_ipp2p: use `skb_header_pointer` and `skb_find_text` Date: Mon, 5 Jun 2023 20:17:34 +0100 Message-Id: <20230605191735.119210-8-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Use `skb_header_pointer` to copy byte-ranges for matching and `skb_find_text` for substring searches. Doing so allows the module to work with non-linear skbs. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 487 ++++++++++++++++++++++++++++++++---------- 1 file changed, 372 insertions(+), 115 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index 1378701605c3..def2d1ffc7bf 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -38,7 +39,9 @@ ipv6_transport_len(const struct sk_buff *skb) struct ipp2p_result_printer { const union nf_inet_addr *saddr, *daddr; short sport, dport; - void (*print)(const union nf_inet_addr *, short, const union nf_inet_addr *, short, bool, unsigned int); + void (*print)(const union nf_inet_addr *, short, + const union nf_inet_addr *, short, + bool, unsigned int); }; static bool iscrlf(const unsigned char *str) @@ -57,12 +60,23 @@ print_result(const struct ipp2p_result_printer *rp, bool result, /* Search for UDP eDonkey/eMule/Kad commands */ static unsigned int -udp_search_edk(const unsigned char *t, const unsigned int packet_len, +udp_search_edk(const struct sk_buff *skb, + const unsigned int packet_off, + const unsigned int packet_len, const struct ipt_p2p_info *info) { + unsigned char buf[36], *t; + if (packet_len < 4) return 0; + t = skb_header_pointer(skb, packet_off, + packet_len < sizeof(buf) ? + packet_len : sizeof(buf), + buf); + if (t == NULL) + return 0; + switch (t[0]) { case 0xe3: /* edonkey */ @@ -176,9 +190,20 @@ udp_search_edk(const unsigned char *t, const unsigned int packet_len, /* Search for UDP Gnutella commands */ static unsigned int -udp_search_gnu(const unsigned char *t, const unsigned int packet_len, +udp_search_gnu(const struct sk_buff *skb, + const unsigned int packet_off, + const unsigned int packet_len, const struct ipt_p2p_info *info) { + unsigned char buf[9], *t; + + t = skb_header_pointer(skb, packet_off, + packet_len < sizeof(buf) ? + packet_len : sizeof(buf), + buf); + if (t == NULL) + return 0; + if (packet_len >= 3 && memcmp(t, "GND", 3) == 0) return IPP2P_GNU * 100 + 51; if (packet_len >= 9 && memcmp(t, "GNUTELLA ", 9) == 0) @@ -188,39 +213,73 @@ udp_search_gnu(const unsigned char *t, const unsigned int packet_len, /* Search for UDP KaZaA commands */ static unsigned int -udp_search_kazaa(const unsigned char *t, const unsigned int packet_len, +udp_search_kazaa(const struct sk_buff *skb, + const unsigned int packet_off, + const unsigned int packet_len, const struct ipt_p2p_info *info) { + unsigned char buf[6], *t; + if (packet_len < 6) return 0; - if (memcmp(t + packet_len - 6, "KaZaA\x00", 6) == 0) + + t = skb_header_pointer(skb, packet_off + packet_len - 6, 6, buf); + if (t == NULL) + return 0; + + if (memcmp(t, "KaZaA\x00", 6) == 0) return IPP2P_KAZAA * 100 + 50; return 0; } /* Search for UDP DirectConnect commands */ static unsigned int -udp_search_directconnect(const unsigned char *t, const unsigned int packet_len, +udp_search_directconnect(const struct sk_buff *skb, + const unsigned int packet_off, + const unsigned int packet_len, const struct ipt_p2p_info *info) { + unsigned char hbuf[6], *head, tbuf, *tail; + if (packet_len < 5) return 0; - if (t[0] != 0x24) + + head = skb_header_pointer(skb, packet_off, packet_len < 7 ? 4 : 6, + hbuf); + if (head == NULL) return 0; - if (t[packet_len-1] != 0x7c) + + tail = skb_header_pointer(skb, packet_off + packet_len - 1, 1, &tbuf); + if (tail == NULL) return 0; - if (memcmp(&t[1], "SR ", 3) == 0) + + if (head[0] != 0x24) + return 0; + if (tail[0] != 0x7c) + return 0; + if (memcmp(&head[1], "SR ", 3) == 0) return IPP2P_DC * 100 + 60; - if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0) + if (packet_len >= 7 && memcmp(&head[1], "Ping ", 5) == 0) return IPP2P_DC * 100 + 61; return 0; } /* Search for UDP BitTorrent commands */ static unsigned int -udp_search_bit(const unsigned char *haystack, const unsigned int packet_len, +udp_search_bit(const struct sk_buff *skb, + const unsigned int packet_off, + const unsigned int packet_len, const struct ipt_p2p_info *info) { + unsigned char buf[32], *haystack; + + haystack = skb_header_pointer(skb, packet_off, + packet_len < sizeof(buf) ? + packet_len : sizeof(buf), + buf); + if (haystack == NULL) + return 0; + switch (packet_len) { case 16: /* ^ 00 00 04 17 27 10 19 80 */ @@ -305,11 +364,22 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len, /* Search for Ares commands */ static unsigned int -search_ares(const unsigned char *payload, const unsigned int plen, +search_ares(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[60], *payload; + if (plen < 3) return 0; + + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; + /* all ares packets start with */ if (payload[1] == 0 && plen - payload[0] == 3) { switch (payload[2]) { @@ -358,11 +428,22 @@ search_ares(const unsigned char *payload, const unsigned int plen, /* Search for SoulSeek commands */ static unsigned int -search_soul(const unsigned char *payload, const unsigned int plen, +search_soul(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[16], *payload; + if (plen < 8) return 0; + + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; + /* match: xx xx xx xx | xx = sizeof(payload) - 4 */ if (get_u32(payload, 0) == plen - 4) { const uint32_t m = get_u32(payload, 4); @@ -461,12 +542,20 @@ search_soul(const unsigned char *payload, const unsigned int plen, if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) { uint32_t y = get_u32(payload, 5); const unsigned char *w; + unsigned int off, len; /* we need 19 chars + string */ if (plen < y + 19) return 0; - w = payload + 9 + y; + off = poff + y + 9; + len = plen - y + 9; + + w = skb_header_pointer(skb, off, + len < sizeof(buf) ? len : sizeof(buf), + buf); + if (w == NULL) + return 0; if (get_u32(w, 0) == 0x01 && (get_u16(w, 4) == 0x4600 || @@ -483,10 +572,19 @@ search_soul(const unsigned char *payload, const unsigned int plen, /* Search for WinMX commands */ static unsigned int -search_winmx(const unsigned char *payload, const unsigned int plen, +search_winmx(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - uint16_t start; + unsigned char buf[149], *payload; + uint16_t start = poff; + + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; if (plen == 4 && memcmp(payload, "SEND", 4) == 0) return IPP2P_WINMX * 100 + 1; @@ -500,23 +598,18 @@ search_winmx(const unsigned char *payload, const unsigned int plen, return 0; if (memcmp(payload, "SEND", 4) == 0) - start = 4; + start += 4; else if (memcmp(payload, "GET", 3) == 0) - start = 3; - else - start = 0; + start += 3; - if (start) { + if (start > poff) { uint8_t count = 0; do { - struct ts_state state; unsigned int pos; - pos = textsearch_find_continuous(info->ts_conf_winmx, - &state, - &payload[start], - plen - start); + pos = skb_find_text((struct sk_buff *)skb, start, + skb->len, info->ts_conf_winmx); if (pos == UINT_MAX) break; @@ -525,7 +618,7 @@ search_winmx(const unsigned char *payload, const unsigned int plen, return IPP2P_WINMX * 100 + 3; start = pos + 2; - } while (start < plen); + } while (start < skb->len); } if (plen == 149 && payload[0] == '8') { @@ -553,11 +646,22 @@ search_winmx(const unsigned char *payload, const unsigned int plen, /* Search for appleJuice commands */ static unsigned int -search_apple(const unsigned char *payload, const unsigned int plen, +search_apple(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[8], *payload; + if (plen < 8) return 0; + + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; + if (memcmp(payload, "ajprot\r\n", 8) == 0) return IPP2P_APPLE * 100; return 0; @@ -565,12 +669,20 @@ search_apple(const unsigned char *payload, const unsigned int plen, /* Search for BitTorrent commands */ static unsigned int -search_bittorrent(const unsigned char *payload, const unsigned int plen, +search_bittorrent(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - struct ts_state state; + unsigned char buf[20], *payload; unsigned int pos; + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; + /* * bitcomet encrypts the first packet, so we have to detect another one * later in the flow. @@ -598,18 +710,18 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen, if (memcmp(payload, "GET /", 5) != 0) return 0; - pos = textsearch_find_continuous(info->ts_conf_bt_info_hash, - &state, &payload[5], plen - 5); + pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len, + info->ts_conf_bt_info_hash); if (pos != UINT_MAX) return IPP2P_BIT * 100 + 1; - pos = textsearch_find_continuous(info->ts_conf_bt_peer_id, - &state, &payload[5], plen - 5); + pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len, + info->ts_conf_bt_peer_id); if (pos != UINT_MAX) return IPP2P_BIT * 100 + 2; - pos = textsearch_find_continuous(info->ts_conf_bt_passkey, - &state, &payload[5], plen - 5); + pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len, + info->ts_conf_bt_passkey); if (pos != UINT_MAX) return IPP2P_BIT * 100 + 4; @@ -618,13 +730,25 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen, /* check for Kazaa get command */ static unsigned int -search_kazaa(const unsigned char *payload, const unsigned int plen, +search_kazaa(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char hbuf[11], *head, tbuf[2], *tail; + if (plen < 13) return 0; - if (iscrlf(&payload[plen - 2]) && - memcmp(payload, "GET /.hash=", 11) == 0) + + head = skb_header_pointer(skb, poff, 11, hbuf); + if (head == NULL) + return 0; + + tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf); + if (tail == NULL) + return 0; + + if (iscrlf(tail) && memcmp(head, "GET /.hash=", 11) == 0) return IPP2P_DATA_KAZAA * 100; return 0; @@ -632,54 +756,87 @@ search_kazaa(const unsigned char *payload, const unsigned int plen, /* check for gnutella get command */ static unsigned int -search_gnu(const unsigned char *payload, const unsigned int plen, +search_gnu(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char hbuf[15], *head, tbuf[2], *tail; + if (plen < 11) return 0; - if (!iscrlf(&payload[plen - 2])) + + head = skb_header_pointer(skb, poff, + plen - 2 < sizeof(hbuf) ? + plen - 2 : sizeof(hbuf), + hbuf); + if (head == NULL) + return 0; + + tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf); + if (tail == NULL) + return 0; + + if (!iscrlf(tail)) return 0; - if (memcmp(payload, "GET /get/", 9) == 0) + if (memcmp(head, "GET /get/", 9) == 0) return IPP2P_DATA_GNU * 100 + 1; - if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0) + if (plen >= 15 && memcmp(head, "GET /uri-res/", 13) == 0) return IPP2P_DATA_GNU * 100 + 2; return 0; } /* check for gnutella get commands and other typical data */ static unsigned int -search_all_gnu(const unsigned char *payload, const unsigned int plen, +search_all_gnu(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - struct ts_state state; - unsigned int c, pos; + unsigned char hbuf[17], *head, tbuf[2], *tail; + unsigned int off, pos; if (plen < 11) return 0; - if (!iscrlf(&payload[plen - 2])) + + head = skb_header_pointer(skb, poff, + plen - 2 < sizeof(hbuf) ? + plen - 2 : sizeof(hbuf), + hbuf); + if (head == NULL) + return 0; + + tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf); + if (tail == NULL) return 0; - if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) + + if (!iscrlf(tail)) + return 0; + + if (plen >= 19 && memcmp(head, "GNUTELLA CONNECT/", 17) == 0) return IPP2P_GNU * 100 + 1; - if (memcmp(payload, "GNUTELLA/", 9) == 0) + + if (memcmp(head, "GNUTELLA/", 9) == 0) return IPP2P_GNU * 100 + 2; if (plen < 22) return 0; - if (memcmp(payload, "GET /get/", 9) == 0) - c = 9; - else if (memcmp(payload, "GET /uri-res/", 13) == 0) - c = 13; + if (memcmp(head, "GET /get/", 9) == 0) + off = 9; + else if (memcmp(head, "GET /uri-res/", 13) == 0) + off = 13; else return 0; - pos = textsearch_find_continuous(info->ts_conf_gnu_x_gnutella, - &state, &payload[c], plen - c); + pos = skb_find_text((struct sk_buff *)skb, poff + off, skb->len, + info->ts_conf_gnu_x_gnutella); if (pos != UINT_MAX) return IPP2P_GNU * 100 + 3; - pos = textsearch_find_continuous(info->ts_conf_gnu_x_queue, - &state, &payload[c], plen - c); + pos = skb_find_text((struct sk_buff *)skb, poff + off, skb->len, + info->ts_conf_gnu_x_queue); + if (pos != UINT_MAX) return IPP2P_GNU * 100 + 3; @@ -689,36 +846,46 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen, /* check for KaZaA download commands and other typical data */ /* plen is guaranteed to be >= 5 (see @matchlist) */ static unsigned int -search_all_kazaa(const unsigned char *payload, const unsigned int plen, +search_all_kazaa(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - struct ts_state state; + unsigned char hbuf[5], *head, tbuf[2], *tail; unsigned int pos; if (plen < 7) /* too short for anything we test for - early bailout */ return 0; - if (!iscrlf(&payload[plen - 2])) + head = skb_header_pointer(skb, poff, sizeof(hbuf), hbuf); + if (head == NULL) + return 0; + + tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf); + if (tail == NULL) return 0; - if (memcmp(payload, "GIVE ", 5) == 0) + if (!iscrlf(tail)) + return 0; + + if (memcmp(head, "GIVE ", 5) == 0) return IPP2P_KAZAA * 100 + 1; - if (memcmp(payload, "GET /", 5) != 0) + if (memcmp(head, "GET /", 5) != 0) return 0; if (plen < 18) /* The next tests would not succeed anyhow. */ return 0; - pos = textsearch_find_continuous(info->ts_conf_kz_x_kazaa_username, - &state, &payload[5], plen - 5); + pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len, + info->ts_conf_kz_x_kazaa_username); if (pos != UINT_MAX) return IPP2P_KAZAA * 100 + 2; - pos = textsearch_find_continuous(info->ts_conf_kz_user_agent, - &state, &payload[5], plen - 5); + pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len, + info->ts_conf_kz_user_agent); if (pos != UINT_MAX) return IPP2P_KAZAA * 100 + 2; @@ -727,11 +894,20 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen, /* fast check for edonkey file segment transfer command */ static unsigned int -search_edk(const unsigned char *payload, const unsigned int plen, +search_edk(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[6], *payload; + if (plen < 6) return 0; + + payload = skb_header_pointer(skb, poff, sizeof(buf), buf); + if (payload == NULL) + return 0; + if (payload[0] != 0xe3) return 0; if (payload[5] == 0x47) @@ -741,13 +917,21 @@ search_edk(const unsigned char *payload, const unsigned int plen, /* intensive but slower search for some edonkey packets including size-check */ static unsigned int -search_all_edk(const unsigned char *payload, const unsigned int plen, +search_all_edk(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[6], *payload; unsigned int cmd; if (plen < 6) return 0; + + payload = skb_header_pointer(skb, poff, sizeof(buf), buf); + if (payload == NULL) + return 0; + if (payload[0] != 0xe3) return 0; @@ -768,11 +952,20 @@ search_all_edk(const unsigned char *payload, const unsigned int plen, /* fast check for Direct Connect send command */ static unsigned int -search_dc(const unsigned char *payload, const unsigned int plen, +search_dc(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char buf[6], *payload; + if (plen < 6) return 0; + + payload = skb_header_pointer(skb, poff, sizeof(buf), buf); + if (payload == NULL) + return 0; + if (payload[0] != 0x24) return 0; if (memcmp(&payload[1], "Send|", 5) == 0) @@ -782,21 +975,35 @@ search_dc(const unsigned char *payload, const unsigned int plen, /* intensive but slower check for all direct connect packets */ static unsigned int -search_all_dc(const unsigned char *payload, const unsigned int plen, +search_all_dc(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { + unsigned char hbuf[8], *head, tbuf, *tail; const unsigned char *t; if (plen < 7) return 0; - if (payload[0] != 0x24) + head = skb_header_pointer(skb, poff, + plen - 1 < sizeof(hbuf) ? + plen - 1 : sizeof(hbuf), + hbuf); + if (head == NULL) return 0; - if (payload[plen-1] != 0x7c) + tail = skb_header_pointer(skb, poff + plen - 1, 1, &tbuf); + if (tail == NULL) return 0; - t = &payload[1]; + if (head[0] != 0x24) + return 0; + + if (tail[0] != 0x7c) + return 0; + + t = &head[1]; /* Client-Hub-Protocol */ if (memcmp(t, "Lock ", 5) == 0) @@ -814,18 +1021,21 @@ search_all_dc(const unsigned char *payload, const unsigned int plen, /* check for mute */ static unsigned int -search_mute(const unsigned char *payload, const unsigned int plen, +search_mute(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { if (plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121) { - //printk(KERN_DEBUG "size hit: %u", size); + unsigned char buf[11], *payload; + + payload = skb_header_pointer(skb, poff, sizeof(buf), buf); + if (payload == NULL) + return 0; + if (memcmp(payload,"PublicKey: ", 11) == 0) { return IPP2P_MUTE * 100 + 0; - /* - if (memcmp(t + size - 14, "\x0aEndPublicKey\x0a", 14) == 0) - printk(KERN_DEBUG "end pubic key hit: %u", size); - */ } } return 0; @@ -833,22 +1043,35 @@ search_mute(const unsigned char *payload, const unsigned int plen, /* check for xdcc */ static unsigned int -search_xdcc(const unsigned char *payload, const unsigned int plen, +search_xdcc(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - struct ts_state state; + unsigned char hbuf[8], *head, tbuf[2], *tail; unsigned int pos; /* search in small packets only */ if (plen <= 20 || plen >= 200) return 0; - if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2])) + head = skb_header_pointer(skb, poff, + plen - 2 < sizeof(hbuf) ? + plen - 2 : sizeof(hbuf), + hbuf); + if (head == NULL) + return 0; + + tail = skb_header_pointer(skb, poff + plen - 2, 2, &tbuf); + if (tail == NULL) + return 0; + + if (memcmp(head, "PRIVMSG ", 8) != 0 || !iscrlf(tail)) return 0; /* seems to be a irc private massage, check for xdcc command */ - pos = textsearch_find_continuous(info->ts_conf_xdcc, - &state, &payload[8], plen - 8); + pos = skb_find_text((struct sk_buff *)skb, poff + 8, skb->len, + info->ts_conf_xdcc); if (pos != UINT_MAX) return IPP2P_XDCC * 100 + 0; @@ -857,10 +1080,23 @@ search_xdcc(const unsigned char *payload, const unsigned int plen, /* search for waste */ static unsigned int -search_waste(const unsigned char *payload, const unsigned int plen, +search_waste(const struct sk_buff *skb, + const unsigned int poff, + const unsigned int plen, const struct ipt_p2p_info *info) { - if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0) + unsigned char buf[9], *payload; + + if (plen < 9) + return 0; + + payload = skb_header_pointer(skb, poff, + plen < sizeof(buf) ? plen : sizeof(buf), + buf); + if (payload == NULL) + return 0; + + if (memcmp(payload, "GET.sha1:", 9) == 0) return IPP2P_WASTE * 100 + 0; return 0; @@ -869,7 +1105,9 @@ search_waste(const unsigned char *payload, const unsigned int plen, static const struct { unsigned int command; unsigned int packet_len; - unsigned int (*function_name)(const unsigned char *, const unsigned int, + unsigned int (*function_name)(const struct sk_buff *, + const unsigned int, + const unsigned int, const struct ipt_p2p_info *); } matchlist[] = { {IPP2P_EDK, 20, search_all_edk}, @@ -894,7 +1132,9 @@ static const struct { static const struct { unsigned int command; unsigned int packet_len; - unsigned int (*function_name)(const unsigned char *, const unsigned int, + unsigned int (*function_name)(const struct sk_buff *, + const unsigned int, + const unsigned int, const struct ipt_p2p_info *); } udp_list[] = { {IPP2P_KAZAA, 14, udp_search_kazaa}, @@ -925,8 +1165,9 @@ ipp2p_print_result_tcp6(const union nf_inet_addr *saddr, short sport, static bool ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph, - const unsigned char *haystack, unsigned int hlen, - const struct ipp2p_result_printer *rp) + const struct sk_buff *skb, unsigned int packet_off, + unsigned int packet_len, + const struct ipp2p_result_printer *rp) { size_t tcph_len = tcph->doff * 4; int i; @@ -935,25 +1176,26 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph, if (tcph->syn) return 0; /* if SYN bit is set bail out */ if (tcph->rst) return 0; /* if RST bit is set bail out */ - if (hlen < tcph_len) { + if (packet_len < tcph_len) { if (info->debug) pr_info("TCP header indicated packet larger than it is\n"); return 0; } - if (hlen == tcph_len) + if (packet_len == tcph_len) return 0; - haystack += tcph_len; - hlen -= tcph_len; + packet_off += tcph_len; + packet_len -= tcph_len; for (i = 0; matchlist[i].command; ++i) { if ((info->cmd & matchlist[i].command) != matchlist[i].command) continue; - if (hlen <= matchlist[i].packet_len) + if (packet_len <= matchlist[i].packet_len) continue; - if (matchlist[i].function_name(haystack, hlen, info)) { + if (matchlist[i].function_name(skb, packet_off, packet_len, + info)) { if (info->debug) - print_result(rp, true, hlen); + print_result(rp, true, packet_len); return true; } } @@ -980,31 +1222,33 @@ ipp2p_print_result_udp6(const union nf_inet_addr *saddr, short sport, static bool ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph, - const unsigned char *haystack, unsigned int hlen, - const struct ipp2p_result_printer *rp) + const struct sk_buff *skb, unsigned int packet_off, + unsigned int packet_len, + const struct ipp2p_result_printer *rp) { size_t udph_len = sizeof(*udph); int i; - if (hlen < udph_len) { + if (packet_len < udph_len) { if (info->debug) pr_info("UDP header indicated packet larger than it is\n"); return 0; } - if (hlen == udph_len) + if (packet_len == udph_len) return 0; - haystack += udph_len; - hlen -= udph_len; + packet_off += udph_len; + packet_len -= udph_len; for (i = 0; udp_list[i].command; ++i) { if ((info->cmd & udp_list[i].command) != udp_list[i].command) continue; - if (hlen <= udp_list[i].packet_len) + if (packet_len <= udp_list[i].packet_len) continue; - if (udp_list[i].function_name(haystack, hlen, info)) { + if (udp_list[i].function_name(skb, packet_off, packet_len, + info)) { if (info->debug) - print_result(rp, true, hlen); + print_result(rp, true, packet_len); return true; } } @@ -1017,9 +1261,8 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par) const struct ipt_p2p_info *info = par->matchinfo; struct ipp2p_result_printer printer; union nf_inet_addr saddr, daddr; - const unsigned char *haystack; /* packet data */ - unsigned int hlen; /* packet data length */ uint8_t family = xt_family(par); + unsigned int packet_len; int protocol; /* @@ -1044,10 +1287,11 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par) if (family == NFPROTO_IPV4) { const struct iphdr *ip = ip_hdr(skb); + saddr.ip = ip->saddr; daddr.ip = ip->daddr; protocol = ip->protocol; - hlen = ip_transport_len(skb); + packet_len = ip_transport_len(skb); } else { const struct ipv6hdr *ip = ipv6_hdr(skb); int thoff = 0; @@ -1057,34 +1301,47 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par) protocol = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL); if (protocol < 0) return 0; - hlen = ipv6_transport_len(skb); + packet_len = ipv6_transport_len(skb); } printer.saddr = &saddr; printer.daddr = &daddr; - haystack = skb_transport_header(skb); switch (protocol) { case IPPROTO_TCP: /* what to do with a TCP packet */ { - const struct tcphdr *tcph = tcp_hdr(skb); + const struct tcphdr *tcph; + struct tcphdr _tcph; + + tcph = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); + if (tcph == NULL) + return 0; printer.sport = ntohs(tcph->source); printer.dport = ntohs(tcph->dest); printer.print = family == NFPROTO_IPV6 ? ipp2p_print_result_tcp6 : ipp2p_print_result_tcp4; - return ipp2p_mt_tcp(info, tcph, haystack, hlen, &printer); + + return ipp2p_mt_tcp(info, tcph, skb, par->thoff, packet_len, + &printer); } case IPPROTO_UDP: /* what to do with a UDP packet */ case IPPROTO_UDPLITE: { - const struct udphdr *udph = udp_hdr(skb); + const struct udphdr *udph; + struct udphdr _udph; + + udph = skb_header_pointer(skb, par->thoff, sizeof(_udph), &_udph); + if (udph == NULL) + return 0; printer.sport = ntohs(udph->source); printer.dport = ntohs(udph->dest); printer.print = family == NFPROTO_IPV6 ? ipp2p_print_result_udp6 : ipp2p_print_result_udp4; - return ipp2p_mt_udp(info, udph, haystack, hlen, &printer); + + return ipp2p_mt_udp(info, udph, skb, par->thoff, packet_len, + &printer); } default: return 0; From patchwork Mon Jun 5 19:17:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Sowden X-Patchwork-Id: 1790620 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=2620:137:e000::1:20; helo=out1.vger.email; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=azazel.net header.i=@azazel.net header.a=rsa-sha256 header.s=20220717 header.b=ILyRLb2T; dkim-atps=neutral Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by legolas.ozlabs.org (Postfix) with ESMTP id 4QZk2w4l3pz20QH for ; Tue, 6 Jun 2023 05:20:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235345AbjFETUT (ORCPT ); Mon, 5 Jun 2023 15:20:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235782AbjFETTz (ORCPT ); Mon, 5 Jun 2023 15:19:55 -0400 Received: from taras.nevrast.org (unknown [IPv6:2a05:d01c:431:aa03:b7e1:333d:ea2a:b14e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 183FA170F for ; Mon, 5 Jun 2023 12:19:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=azazel.net; s=20220717; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=PJT81BzRs/yHfDDfeWxI/KSga8MxqnzMfUDsCESegEk=; b=ILyRLb2T0Vd9H5eCngLnBoo8wY pdLpXTp9b2nWbjPxojwS6bH9KtKrJcH+LKrwm0E6c1OAIorB5SfdGc7g/MfiPdWixfSTyXjQEtbA7 15rXhPsZjoWtQrDSv41U6n33ny2W9ar/sr9xIY+gH8E46Z2pYmzJ/IGKwcXUH7iZkX+DUEtPqGH2S wqzu8i6XDksPsaBvg7+yr7Va4GH9MbYjFzo2r8hhrv0mcZO746kFMJDERt3leOKfSwNOp9PMx15Z+ JKGAC0OqZQmQRtUM223UG+PedepYxKo7HXV4CPjYVQth67MLkE5Wchb34xzn0QXqg7nRSdFDNo6jf kmRzCV1g==; Received: from [2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608] (helo=ulthar.dreamlands) by taras.nevrast.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1q6FjL-00H0rc-FC for netfilter-devel@vger.kernel.org; Mon, 05 Jun 2023 20:19:03 +0100 From: Jeremy Sowden To: Netfilter Devel Subject: [PATCH xtables-addons 8/8] xt_ipp2p: drop requirement that skb is linear Date: Mon, 5 Jun 2023 20:17:35 +0100 Message-Id: <20230605191735.119210-9-jeremy@azazel.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230605191735.119210-1-jeremy@azazel.net> References: <20230605191735.119210-1-jeremy@azazel.net> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:8b0:135f:bcd1:e0cb:4eff:fedf:e608 X-SA-Exim-Mail-From: jeremy@azazel.net X-SA-Exim-Scanned: No (on taras.nevrast.org); SAEximRunCond expanded to false X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RDNS_NONE,SPF_HELO_FAIL, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org It is no longer necessary. Signed-off-by: Jeremy Sowden --- extensions/xt_ipp2p.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c index def2d1ffc7bf..c7712660816d 100644 --- a/extensions/xt_ipp2p.c +++ b/extensions/xt_ipp2p.c @@ -1278,13 +1278,6 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par) return 0; } - /* make sure that skb is linear */ - if (skb_is_nonlinear(skb)) { - if (info->debug) - printk("IPP2P.match: nonlinear skb found\n"); - return 0; - } - if (family == NFPROTO_IPV4) { const struct iphdr *ip = ip_hdr(skb);