From nobody Tue Sep 06 11:19:47 2022 X-Original-To: dev-commits-src-main@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 4MMNFw1Lxjz4bYxp; Tue, 6 Sep 2022 11:19:48 +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 4MMNFw0tzGz3mXD; Tue, 6 Sep 2022 11:19:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662463188; 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=vFOQrHohM9AHYfRkOqOfUcAhp5GgxgtYjVMf3xvZW/Q=; b=sTRjklH5n8G1aku9O1kIZ0N/NLEXJ5C6edXiTS2UIRQ8/dXjNUB1vKk3hSjGpIsEpWKdEP hjeGG5UFZzCB0rY8SARBg6iIRIzmgOMoXuxxMQR0O9KlHdiXIxMoLMtMSyFJl94Y0ZZEg/ MxjeJIO5Fr/MBzJ+abWeTWF0s9LC1mVsFzL/pEVLp/R64KJITOE3GXP5VfbmVOn2QVwQfS kuUM/7P07pYwIrno4s2pYPCPvAucbqjCGpyviAezutq/gD76RC9drEmApV6mwIMYidCi5A Ks0Da+iCwlLlHEnNqfSyHLYGD6wSPmUS0bZ5qi7zk32tPZ07DONRAtMuzoTCrA== 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 4MMNFw01B1z18XH; Tue, 6 Sep 2022 11:19:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 286BJll3024936; Tue, 6 Sep 2022 11:19:47 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 286BJlMc024935; Tue, 6 Sep 2022 11:19:47 GMT (envelope-from git) Date: Tue, 6 Sep 2022 11:19:47 GMT Message-Id: <202209061119.286BJlMc024935@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: 585a5ed0bef4 - main - pfctl: fix recrusive printing of anchors List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: 585a5ed0bef4a0b874c8fa495ae53901799759c3 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662463188; 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=vFOQrHohM9AHYfRkOqOfUcAhp5GgxgtYjVMf3xvZW/Q=; b=gWvVAVfZdXPqimfO+19n2AAWhA6eYl1sGkqCkGS0TqnEwN8KR7CLhVu/D4Fn5g8Wgs6f8H 90017MiK3/AJPqbQYSZwlnE0Qf9WJOhtfdWPXkPp/o0q+1yzWrDVtxBCA4iMBBtBxY5iAN 2wXl8I72f1tHAprZpGNz+sZrLpZAEvmxdv79avto8a22l8QpPLiMkJNokfMhKCAqtFUkyI cy681uR2Adi5yfCtWIC1mRHaBYvdqrQvht+3hV7P/jCqXiE/pUA1LhR3KPupDPEwsIRK3C zl0NImHh4wgvIhF6VrpZODmqj9FFOHuE0gDtzdHdOvV3zGitCqw9lTThOpUizQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1662463188; a=rsa-sha256; cv=none; b=sS31iiVKIHIrDGDkbSX1OIyPplC4bqN5UTrtOGlpYGrXmG8uk6ySiwCrqZA9QbRGBJM4LC h/IZy75w9bsFtWXMJH0q/w+z9UAEsWu7+CtfcbrFe9Q0vX0jyW4oppw+TD7ejQ1cl5RsFT KqC/PtOmoBdIXNd8x3NOOgYFzl1mEZ6vmCe0P/ZcFjwUccq4Jy82bWi9huQuIj4Gg97Gbv t3odA3dspRoYFqkf/t2OMRKMqQC1cKGjRn5CHg9nOb6LpXRvHVvkw3vBsQ0JmUoYiaIgzS ZFwEvNsfI7EiPOUIZu3FG0XWsVVowoHF07ULJJtJ2ttYZcS9ocskZUcH4qSIKQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=585a5ed0bef4a0b874c8fa495ae53901799759c3 commit 585a5ed0bef4a0b874c8fa495ae53901799759c3 Author: Kristof Provost AuthorDate: 2022-09-01 08:16:24 +0000 Commit: Kristof Provost CommitDate: 2022-09-06 08:42:10 +0000 pfctl: fix recrusive printing of anchors Fix a couple of problems with printing of anchors, in particular recursive printing, both of inline anchors and when requested explicitly with a '*' in the anchor. - Correct recursive printing of wildcard anchors (recurse into child anchors rather than rules, which don't exist) - Print multi-part anchor paths correctly (pr6065) - Fix comments and prevent users from specifying multi-component names for inline anchors. tested by phessler ok henning Also fix the relevant pfctl test case to reflect the new (and now correct) behaviour). MFC after: 3 weeks Obtained from: OpenBSD (mcbride, f9a568a27c740528301ca3419316c85a9fc7f1de) Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D36416 --- sbin/pfctl/parse.y | 16 ++++- sbin/pfctl/pfctl.c | 122 +++++++++++++++++++++++++++------------ sbin/pfctl/pfctl_parser.c | 6 +- sbin/pfctl/tests/files/pf0100.ok | 10 ++-- 4 files changed, 107 insertions(+), 47 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 7bb6223319c4..5d0320e909fb 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -891,7 +891,12 @@ pfa_anchor : '{' pf->asd++; pf->bn++; - /* create a holding ruleset in the root */ + /* + * Anchor contents are parsed before the anchor rule + * production completes, so we don't know the real + * location yet. Create a holding ruleset in the root; + * contents will be moved afterwards. + */ snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); rs = pf_find_or_create_ruleset(ta); if (rs == NULL) @@ -928,7 +933,14 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto memset(&r, 0, sizeof(r)); if (pf->astack[pf->asd + 1]) { - /* move inline rules into relative location */ + if ($2 && strchr($2, '/') != NULL) { + free($2); + yyerror("anchor paths containing '/' " + "cannot be used for inline anchors."); + YYERROR; + } + + /* Move inline rules into relative location. */ pfctl_anchor_setup(&r, &pf->astack[pf->asd]->ruleset, $2 ? $2 : pf->alast->name); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 31499a9a86b0..0445fdd32ea7 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -100,7 +100,7 @@ int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int); void pfctl_print_rule_counters(struct pfctl_rule *, int); int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int); -int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); +int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int); int pfctl_show_nat(int, char *, int, char *, int); int pfctl_show_src_nodes(int, int); int pfctl_show_states(int, const char *, int); @@ -1153,7 +1153,7 @@ pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format, int pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, - char *anchorname, int depth) + char *anchorname, int depth, int wildcard) { struct pfctl_rules_info ri; struct pfctl_rule rule; @@ -1161,15 +1161,65 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, u_int32_t nr, header = 0; int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); int numeric = opts & PF_OPT_NUMERIC; - int len = strlen(path); - int brace; - int ret; - char *p; + int len = strlen(path), ret = 0; + char *npath, *p; - if (path[0]) - snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); - else - snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); + /* + * Truncate a trailing / and * on an anchorname before searching for + * the ruleset, this is syntactic sugar that doesn't actually make it + * to the kernel. + */ + if ((p = strrchr(anchorname, '/')) != NULL && + p[1] == '*' && p[2] == '\0') { + p[0] = '\0'; + } + + if (anchorname[0] == '/') { + if ((npath = calloc(1, MAXPATHLEN)) == NULL) + errx(1, "pfctl_rules: calloc"); + snprintf(npath, MAXPATHLEN, "%s", anchorname); + } else { + if (path[0]) + snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); + else + snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); + npath = path; + } + + /* + * If this anchor was called with a wildcard path, go through + * the rulesets in the anchor rather than the rules. + */ + if (wildcard && (opts & PF_OPT_RECURSE)) { + struct pfioc_ruleset prs; + u_int32_t mnr, nr; + + memset(&prs, 0, sizeof(prs)); + memcpy(prs.path, npath, sizeof(prs.path)); + if (ioctl(dev, DIOCGETRULESETS, &prs)) { + if (errno == EINVAL) + fprintf(stderr, "Anchor '%s' " + "not found.\n", anchorname); + else + err(1, "DIOCGETRULESETS"); + } + mnr = prs.nr; + + pfctl_print_rule_counters(&rule, opts); + for (nr = 0; nr < mnr; ++nr) { + prs.nr = nr; + if (ioctl(dev, DIOCGETRULESET, &prs)) + err(1, "DIOCGETRULESET"); + INDENT(depth, !(opts & PF_OPT_VERBOSE)); + printf("anchor \"%s\" all {\n", prs.name); + pfctl_show_rules(dev, npath, opts, + format, prs.name, depth + 1, 0); + INDENT(depth, !(opts & PF_OPT_VERBOSE)); + printf("}\n"); + } + path[len] = '\0'; + return (0); + } if (opts & PF_OPT_SHOWALL) { ret = pfctl_get_rules_info(dev, &ri, PF_PASS, path); @@ -1260,32 +1310,30 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, break; } case PFCTL_SHOW_RULES: - brace = 0; if (rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; INDENT(depth, !(opts & PF_OPT_VERBOSE)); + print_rule(&rule, anchor_call, rule_numbers, numeric); + + /* + * If this is a 'unnamed' brace notation + * anchor, OR the user has explicitly requested + * recursion, print it recursively. + */ if (anchor_call[0] && - ((((p = strrchr(anchor_call, '_')) != NULL) && - ((void *)p == (void *)anchor_call || - *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { - brace++; - int aclen = strlen(anchor_call); - if (anchor_call[aclen - 1] == '*') - anchor_call[aclen - 2] = '\0'; - } - p = &anchor_call[0]; - - print_rule(&rule, p, rule_numbers, numeric); - if (brace) + (((p = strrchr(anchor_call, '/')) ? + p[1] == '_' : anchor_call[0] == '_') || + opts & PF_OPT_RECURSE)) { printf(" {\n"); - else - printf("\n"); - pfctl_print_rule_counters(&rule, opts); - if (brace) { - pfctl_show_rules(dev, path, opts, format, - p, depth + 1); + pfctl_print_rule_counters(&rule, opts); + pfctl_show_rules(dev, npath, opts, format, + anchor_call, depth + 1, + rule.anchor_wildcard); INDENT(depth, !(opts & PF_OPT_VERBOSE)); printf("}\n"); + } else { + printf("\n"); + pfctl_print_rule_counters(&rule, opts); } break; case PFCTL_SHOW_NOTHING: @@ -1293,12 +1341,10 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, } pfctl_clear_pool(&rule.rpool); } - path[len] = '\0'; - return (0); error: path[len] = '\0'; - return (-1); + return (ret); } int @@ -1909,7 +1955,7 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) if (pf->opts & PF_OPT_VERBOSE) { INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); - print_rule(r, r->anchor ? r->anchor->name : "", + print_rule(r, name, pf->opts & PF_OPT_VERBOSE2, pf->opts & PF_OPT_NUMERIC); if (was_present) @@ -2908,12 +2954,12 @@ main(int argc, char *argv[]) case 'r': pfctl_load_fingerprints(dev, opts); pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, - anchorname, 0); + anchorname, 0, 0); break; case 'l': pfctl_load_fingerprints(dev, opts); pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, - anchorname, 0); + anchorname, 0, 0); break; case 'n': pfctl_load_fingerprints(dev, opts); @@ -2951,12 +2997,12 @@ main(int argc, char *argv[]) pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0); pfctl_show_nat(dev, path, opts, anchorname, 0); - pfctl_show_rules(dev, path, opts, 0, anchorname, 0); + pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0); pfctl_show_altq(dev, ifaceopt, opts, 0); pfctl_show_states(dev, ifaceopt, opts); pfctl_show_src_nodes(dev, opts); pfctl_show_status(dev, opts); - pfctl_show_rules(dev, path, opts, 1, anchorname, 0); + pfctl_show_rules(dev, path, opts, 1, anchorname, 0, 0); pfctl_show_timeouts(dev, opts); pfctl_show_limits(dev, opts); pfctl_show_tables(anchorname, opts); @@ -2979,7 +3025,7 @@ main(int argc, char *argv[]) pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING, anchorname, 0); pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, - anchorname, 0); + anchorname, 0, 0); } if (clearopt != NULL) { diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index c65fe6abe3f6..260c754f7209 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -811,6 +811,7 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer "anchor", "nat-anchor", "nat-anchor", "binat-anchor", "binat-anchor", "rdr-anchor", "rdr-anchor" }; int i, opts; + char *p; if (verbose) printf("@%d ", r->nr); @@ -819,9 +820,10 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer else if (r->action > PF_NORDR) printf("action(%d)", r->action); else if (anchor_call[0]) { - if (anchor_call[0] == '_') { + p = strrchr(anchor_call, '/'); + if (p ? p[1] == '_' : anchor_call[0] == '_') printf("%s", anchortypes[r->action]); - } else + else printf("%s \"%s\"", anchortypes[r->action], anchor_call); } else { diff --git a/sbin/pfctl/tests/files/pf0100.ok b/sbin/pfctl/tests/files/pf0100.ok index 6d1740f308bc..9f4427379bc7 100644 --- a/sbin/pfctl/tests/files/pf0100.ok +++ b/sbin/pfctl/tests/files/pf0100.ok @@ -1,14 +1,14 @@ pass all flags S/SA keep state -anchor "/b" all -anchor "/3" all +anchor "a/b" all +anchor "1/2/3" all anchor "relative" all { pass in on lo0 all flags S/SA keep state label "TEST1" } -anchor "/*" all -anchor "/*" all +anchor "camield/*" all +anchor "relayd/*" all anchor "foo" in on lo0 all { anchor "bar" in all { - anchor "/3" all + anchor "/1/2/3" all anchor "/relative" all pass in on lo0 all flags S/SA keep state label "FOO" }