From nobody Fri Oct 6 16:16:35 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4S2D841nSTz4wyn2; Fri, 6 Oct 2023 16:16:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4S2D836ChWz4KtN; Fri, 6 Oct 2023 16:16:35 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696608995; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QSeMzntKrKJM2gp1OJkar78dYATkug8CSzy7PFSQCR0=; b=efTDbWQOCAWDFDKX09iVA0kdt2NEUXoWqAMZGbOUuTc0sAyjUx1l6E4VZBAE5IC6am/s7X cEh3+VvZsqWvCnFrgtQifM1bhDvnwpbYH4Vxjuj1NRvWfGViqsAtRXFaJUVcS5yXBuokHZ /X50gAfya/r6HudNmuQR7Bz9CBQcOCftpFDMZn/u/u/NPFrNLi3G86hlqUq/hx8xU1vBr5 2eNqqZGqmhchbOy2vtN5wN4m71A8jaupgg5hWGjFqJT4u+5adXOLH19h+g6JpjskCQYD05 x52r+QctpWas0ykW20J2qtJrZyGM2F5X52Xc71Yxu1UYFIVu9KNwUIZlT1BYNA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1696608995; a=rsa-sha256; cv=none; b=Y+jK8kytKd6Cg4K6IlsOIM/5XE3KtFp4ImEbMx+YZF8nv8NQtPf9yJO857whkxw17mf+VZ EMO3g44FhVLJnJUOpIheqHCohyDx8XA4x44e3Q8t38LjuvhkkytW2+pLev6GsBhrYByKjU MEMyTYjky7WMYyohCf7qfyb0WFmrjI0CokoSodRtK9mQAtqoVdq+158/6ZGkb7HZKD/E5e Lcmk+HTJ5RocOxIwaFnhbh0nfK80HVse2N7LAJvL4S/2d/j3ixQjbeHbQXc4hQuEqykxN2 hTM2j6X121jRv+UaIZw4H+6tVXE2KTkLAN/5BcLxW0gf5vRUBeo3FA05tJPLgA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696608995; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=QSeMzntKrKJM2gp1OJkar78dYATkug8CSzy7PFSQCR0=; b=nVUY6sk2sRCSwPD/DGUlEVtnMIuriKA91c5M9gCYV2NCq4osLwarWscV85ZzoKfGjuk1PQ NJBLsiswIEEzH6+ZzbSACP+ttjvRDERZeeN18TMHYGSpNw/PTzcD67S7wluXhkktcSmml/ ZR08fU4sAw+Rq+RZMK3NDX7AJ4aHrHkknjff0f5X/bCzyJJjxjABkZG/RqkmVuy3lC898o 52HvyPKoOXIsMXPAA2zebz80VtCtOlP5Yq6vsdBBH9xzoVTfhhjJc5PloKU5BHtdpsBAqn LAOor87mmyEzUj3iSvNLuDs1+jFXjfarkFymdtOvllflpD9KJtX15NrhXIPGFQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4S2D835HBLzvjW; Fri, 6 Oct 2023 16:16:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 396GGZMo077095; Fri, 6 Oct 2023 16:16:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 396GGZho077093; Fri, 6 Oct 2023 16:16:35 GMT (envelope-from git) Date: Fri, 6 Oct 2023 16:16:35 GMT Message-Id: <202310061616.396GGZho077093@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 7ce98cf2f87a - main - pfctl: fix incorrect mask on dynamic address List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7ce98cf2f87a22240b66e4c38fd887431a25bf7d Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=7ce98cf2f87a22240b66e4c38fd887431a25bf7d commit 7ce98cf2f87a22240b66e4c38fd887431a25bf7d Author: Kristof Provost AuthorDate: 2023-10-06 12:20:17 +0000 Commit: Kristof Provost CommitDate: 2023-10-06 16:11:28 +0000 pfctl: fix incorrect mask on dynamic address A PF rule using an IPv4 address followed by an IPv6 address and then a dynamic address, e.g. "pass from {192.0.2.1 2001:db8::1} to (pppoe0)", will have an incorrect /32 mask applied to the dynamic address. MFC after: 3 weeks Obtained from: OpenBSD See also: https://ftp.openbsd.org/pub/OpenBSD/patches/5.6/common/007_pfctl.patch.sig Sponsored by: Rubicon Communications, LLC ("Netgate") Event: Oslo Hackathon at Modirum --- sbin/pfctl/parse.y | 39 +++++++++++++++++++++++++++++++++++- sbin/pfctl/pfctl_parser.c | 30 ++++++++++++++++++++++----- sbin/pfctl/pfctl_parser.h | 1 + sbin/pfctl/tests/files/pf0102.ok | 4 ++-- sbin/pfctl/tests/files/pf1018.in | 1 + sbin/pfctl/tests/files/pf1018.ok | 2 ++ sbin/pfctl/tests/pfctl_test_list.inc | 1 + 7 files changed, 70 insertions(+), 8 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 041dcb0587b3..17227b674814 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -4720,6 +4720,10 @@ natrule : nataction interface af proto fromto tag tagged rtable remove_invalid_hosts(&$9->host, &r.af); if (invalid_redirect($9->host, r.af)) YYERROR; + if ($9->host->addr.type == PF_ADDR_DYNIFTL) { + if (($9->host = gen_dynnode($9->host, r.af)) == NULL) + err(1, "calloc"); + } if (check_netmask($9->host, r.af)) YYERROR; @@ -4936,6 +4940,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag yyerror("binat ip versions must match"); YYERROR; } + if ($8->addr.type == PF_ADDR_DYNIFTL) { + if (($8 = gen_dynnode($8, binat.af)) == NULL) + err(1, "calloc"); + } if (check_netmask($8, binat.af)) YYERROR; memcpy(&binat.src.addr, &$8->addr, @@ -4951,6 +4959,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag yyerror("binat ip versions must match"); YYERROR; } + if ($9->addr.type == PF_ADDR_DYNIFTL) { + if (($9 = gen_dynnode($9, binat.af)) == NULL) + err(1, "calloc"); + } if (check_netmask($9, binat.af)) YYERROR; memcpy(&binat.dst.addr, &$9->addr, @@ -4980,6 +4992,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag "a single address"); YYERROR; } + if ($13->host->addr.type == PF_ADDR_DYNIFTL) { + if (($13->host = gen_dynnode($13->host, binat.af)) == NULL) + err(1, "calloc"); + } if (check_netmask($13->host, binat.af)) YYERROR; @@ -5982,7 +5998,7 @@ expand_rule(struct pfctl_rule *r, char tagname[PF_TAG_NAME_SIZE]; char match_tagname[PF_TAG_NAME_SIZE]; struct pf_pooladdr *pa; - struct node_host *h; + struct node_host *h, *osrch, *odsth; u_int8_t flags, flagset, keep_state; memcpy(label, r->label, sizeof(r->label)); @@ -6043,6 +6059,18 @@ expand_rule(struct pfctl_rule *r, sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) errx(1, "expand_rule: strlcpy"); + osrch = odsth = NULL; + if (src_host->addr.type == PF_ADDR_DYNIFTL) { + osrch = src_host; + if ((src_host = gen_dynnode(src_host, r->af)) == NULL) + err(1, "expand_rule: calloc"); + } + if (dst_host->addr.type == PF_ADDR_DYNIFTL) { + odsth = dst_host; + if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL) + err(1, "expand_rule: calloc"); + } + error += check_netmask(src_host, r->af); error += check_netmask(dst_host, r->af); @@ -6121,6 +6149,15 @@ expand_rule(struct pfctl_rule *r, added++; } + if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) { + free(src_host); + src_host = osrch; + } + if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) { + free(dst_host); + dst_host = odsth; + } + )))))))))); FREE_LIST(struct node_if, interfaces); diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 936c5ec53759..925848055bba 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1306,16 +1306,12 @@ int check_netmask(struct node_host *h, sa_family_t af) { struct node_host *n = NULL; - struct pf_addr *m; + struct pf_addr *m; for (n = h; n != NULL; n = n->next) { if (h->addr.type == PF_ADDR_TABLE) continue; m = &h->addr.v.a.mask; - /* fix up netmask for dynaddr */ - if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && - unmask(m, AF_INET6) > 32) - set_ipmask(n, 32); /* netmasks > 32 bit are invalid on v4 */ if (af == AF_INET && (m->addr32[1] || m->addr32[2] || m->addr32[3])) { @@ -1327,6 +1323,30 @@ check_netmask(struct node_host *h, sa_family_t af) return (0); } +struct node_host * +gen_dynnode(struct node_host *h, sa_family_t af) +{ + struct node_host *n; + struct pf_addr *m; + + if (h->addr.type != PF_ADDR_DYNIFTL) + return (NULL); + + if ((n = calloc(1, sizeof(*n))) == NULL) + return (NULL); + bcopy(h, n, sizeof(*n)); + n->ifname = NULL; + n->next = NULL; + n->tail = NULL; + + /* fix up netmask */ + m = &n->addr.v.a.mask; + if (af == AF_INET && unmask(m, AF_INET6) > 32) + set_ipmask(n, 32); + + return (n); +} + /* interface lookup routines */ static struct node_host *iftab; diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 83a4880106a8..d0f3bc3c303c 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -360,6 +360,7 @@ extern const struct pf_timeout pf_timeouts[]; void set_ipmask(struct node_host *, u_int8_t); int check_netmask(struct node_host *, sa_family_t); int unmask(struct pf_addr *, sa_family_t); +struct node_host *gen_dynnode(struct node_host *, sa_family_t); void ifa_load(void); int get_query_socket(void); struct node_host *ifa_exists(char *); diff --git a/sbin/pfctl/tests/files/pf0102.ok b/sbin/pfctl/tests/files/pf0102.ok index 3233ca5a2643..1c76ec2725ba 100644 --- a/sbin/pfctl/tests/files/pf0102.ok +++ b/sbin/pfctl/tests/files/pf0102.ok @@ -1,8 +1,8 @@ pass inet from 1.1.1.1 to (self) flags S/SA keep state -pass inet6 from 2002:: to (self)/32 flags S/SA keep state +pass inet6 from 2002:: to (self) flags S/SA keep state pass inet6 from 2002:: to (self) flags S/SA keep state pass inet from 1.1.1.1 to (self) flags S/SA keep state pass inet from 1.1.1.1 to (self) flags S/SA keep state -pass inet6 from 2002:: to (self)/32 flags S/SA keep state +pass inet6 from 2002:: to (self)/40 flags S/SA keep state pass inet6 from 2002:: to (self)/40 flags S/SA keep state pass inet from 1.1.1.1 to (self) flags S/SA keep state diff --git a/sbin/pfctl/tests/files/pf1018.in b/sbin/pfctl/tests/files/pf1018.in new file mode 100644 index 000000000000..90f0a3a0bab7 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1018.in @@ -0,0 +1 @@ +pass from { 192.0.2.1 2001:db8::1 } to (pppoe0) diff --git a/sbin/pfctl/tests/files/pf1018.ok b/sbin/pfctl/tests/files/pf1018.ok new file mode 100644 index 000000000000..04950f0035b8 --- /dev/null +++ b/sbin/pfctl/tests/files/pf1018.ok @@ -0,0 +1,2 @@ +pass inet from 192.0.2.1 to (pppoe0) flags S/SA keep state +pass inet6 from 2001:db8::1 to (pppoe0) flags S/SA keep state diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc index 98ea3257d492..4a63c0ba48b7 100644 --- a/sbin/pfctl/tests/pfctl_test_list.inc +++ b/sbin/pfctl/tests/pfctl_test_list.inc @@ -126,3 +126,4 @@ PFCTL_TEST(1014, "Ethernet rule with one label") PFCTL_TEST(1015, "Ethernet rule with several labels") PFCTL_TEST(1016, "Ethernet rule with ridentifier and one label") PFCTL_TEST(1017, "Ethernet rule with ridentifier and several labels") +PFCTL_TEST(1018, "Test dynamic address mask")