summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2006-11-07 01:12:02 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2006-11-07 01:12:02 +0000
commit34c87bf757df651c95889d1a6842e603bbc4096c (patch)
treef602c290fb342c31afa32bfa734c1c0053670f46
parent653977e22f93c345520ca28604abf2e6a3203e76 (diff)
Unbreak authpf by handling non-inline anchors separately from the { } anchors
as pf_find_or_create_ruleset() will mangle relative anchor names and wildcards. Also fixes some nits with nesting and printing inline anchors. ok deraadt@
-rw-r--r--sbin/pfctl/parse.y57
-rw-r--r--sbin/pfctl/pfctl.c126
2 files changed, 125 insertions, 58 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 3066bdb00fd..5d1daccf9c6 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.515 2006/10/31 14:17:44 mcbride Exp $ */
+/* $OpenBSD: parse.y,v 1.516 2006/11/07 01:12:01 mcbride Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -659,15 +659,17 @@ pfa_anchorlist : pfrule optnl
pfa_anchor : '{'
{
- char tmp_anchorname[PF_ANCHOR_NAME_SIZE];
+ char ta[PF_ANCHOR_NAME_SIZE];
struct pf_ruleset *rs;
+ /* steping into a brace anchor */
pf->asd++;
pf->bn++;
pf->brace = 1;
- snprintf(tmp_anchorname, PF_ANCHOR_NAME_SIZE,
- "_%d", pf->bn);
- rs = pf_find_or_create_ruleset(tmp_anchorname);
+
+ /* create a holding ruleset in the root */
+ snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
+ rs = pf_find_or_create_ruleset(ta);
if (rs == NULL)
err(1, "pfa_anchor: pf_find_or_create_ruleset");
pf->astack[pf->asd] = rs->anchor;
@@ -701,30 +703,31 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
memset(&r, 0, sizeof(r));
if (pf->astack[pf->asd + 1]) {
- if ($2) {
- struct pf_ruleset *src =
- &pf->alast->ruleset;
- struct pf_ruleset *dst =
- pf_find_or_create_ruleset($2);
-
- if (!dst)
- err(1, "anchorrule: unable to "
- "create ruleset");
- if (dst->anchor->refcnt) {
- yyerror("inline anchor "
- "already exists\n");
+ /* move inline rules into relative location */
+ pf_anchor_setup(&r,
+ &pf->astack[pf->asd]->ruleset,
+ $2 ? $2 : pf->alast->name);
+
+ if (r.anchor == NULL)
+ err(1, "anchorrule: unable to "
+ "create ruleset");
+
+ if (pf->alast != r.anchor) {
+ if (r.anchor->match) {
+ yyerror("inline anchor '%s' "
+ "already exists",
+ r.anchor->name);
YYERROR;
}
-
- mv_rules(src, dst);
- pf_remove_if_empty_ruleset(src);
- pf->alast = dst->anchor;
+ mv_rules(&pf->alast->ruleset,
+ &r.anchor->ruleset);
}
- r.anchor = pf->alast;
+ pf_remove_if_empty_ruleset(&pf->alast->ruleset);
+ pf->alast = r.anchor;
} else {
if (!$2) {
yyerror("anchors without explicit "
- "rules must specify a name\n");
+ "rules must specify a name");
YYERROR;
}
}
@@ -4334,7 +4337,7 @@ expand_label_nr(const char *name, char *label, size_t len)
char n[11];
if (strstr(label, name) != NULL) {
- snprintf(n, sizeof(n), "%u", pf->anchor->refcnt);
+ snprintf(n, sizeof(n), "%u", pf->anchor->match);
expand_label_str(label, len, name, n);
}
}
@@ -4764,7 +4767,7 @@ expand_rule(struct pf_rule *r,
if (rule_consistent(r, anchor_call[0]) < 0 || error)
yyerror("skipping rule due to errors");
else {
- r->nr = pf->anchor->refcnt++;
+ r->nr = pf->astack[pf->asd]->match++;
pfctl_add_rule(pf, r, anchor_call);
added++;
}
@@ -5305,7 +5308,9 @@ mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
!= NULL) {
TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
+ dst->anchor->match++;
}
+ src->anchor->match = 0;
while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
!= NULL) {
TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
@@ -5313,8 +5318,6 @@ mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
r, entries);
}
}
- dst->anchor->refcnt = src->anchor->refcnt;
- src->anchor->refcnt = 0;
}
void
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 44aba92d073..d3c2fc1e32e 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.254 2006/11/05 07:19:30 mcbride Exp $ */
+/* $OpenBSD: pfctl.c,v 1.255 2006/11/07 01:12:01 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -652,6 +652,7 @@ pfctl_show_rules(int dev, char *path, int opts, int format,
int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
int len = strlen(path);
int brace;
+ char *p;
if (path[0])
snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
@@ -754,18 +755,27 @@ pfctl_show_rules(int dev, char *path, int opts, int format,
if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
labels = 1;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
- print_rule(&pr.rule, pr.anchor_call, rule_numbers);
- if (strlen(pr.anchor_call) &&
- (pr.anchor_call[0] == '_' ||
- opts & PF_OPT_RECURSE)) {
+ if ((((p = strrchr(pr.anchor_call, '_')) != NULL) &&
+ ((void *)p == (void *)pr.anchor_call ||
+ *(--p) == '/')) || opts & PF_OPT_RECURSE) {
brace++;
- printf(" {\n");
+ if ((p = strrchr(pr.anchor_call, '/')) !=
+ NULL)
+ p++;
+ else
+ p = &pr.anchor_call[0];
} else
+ p = &pr.anchor_call[0];
+
+ print_rule(&pr.rule, p, rule_numbers);
+ if (brace)
+ printf(" {\n");
+ else
printf("\n");
pfctl_print_rule_counters(&pr.rule, opts);
- if (brace) {
+ if (brace) {
pfctl_show_rules(dev, path, opts, format,
- pr.anchor_call, depth + 1);
+ p, depth + 1);
INDENT(depth, !(opts & PF_OPT_VERBOSE));
printf("}\n");
}
@@ -1003,6 +1013,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
u_int8_t rs_num;
struct pf_rule *rule;
struct pf_ruleset *rs;
+ char *p;
rs_num = pf_get_ruleset_number(r->action);
if (rs_num == PF_RULESET_MAX)
@@ -1010,9 +1021,28 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
rs = &pf->anchor->ruleset;
-
- if (anchor_call[0] && r->anchor == NULL)
- r->anchor = pf_find_or_create_ruleset(anchor_call)->anchor;
+ if (anchor_call[0] && r->anchor == NULL) {
+ /*
+ * Don't make non-brace anchors part of the main anchor pool.
+ */
+ if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
+ err(1, "pfctl_add_rule: calloc");
+
+ pf_init_ruleset(&r->anchor->ruleset);
+ r->anchor->ruleset.anchor = r->anchor;
+ if (strlcpy(r->anchor->path, anchor_call,
+ sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
+ errx(1, "pfctl_add_rule: strlcpy");
+ if ((p = strrchr(anchor_call, '/')) != NULL) {
+ if (!strlen(p))
+ err(1, "pfctl_add_rule: bad anchor name %s",
+ anchor_call);
+ } else
+ p = (char *)anchor_call;
+ if (strlcpy(r->anchor->name, p,
+ sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
+ errx(1, "pfctl_add_rule: strlcpy");
+ }
if ((rule = calloc(1, sizeof(*rule))) == NULL)
err(1, "calloc");
@@ -1069,26 +1099,26 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs,
else
snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name);
- if (pf->opts & PF_OPT_VERBOSE && depth) {
+ if (depth) {
if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) {
brace++;
- printf(" {\n");
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if ((error = pfctl_ruleset_trans(pf,
- path, rs->anchor))) {
- printf("pfctl_load_rulesets: "
- "pfctl_ruleset_trans %d\n", error);
- goto error;
- }
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf(" {\n");
+ if ((pf->opts & PF_OPT_NOACTION) == 0 &&
+ (error = pfctl_ruleset_trans(pf,
+ path, rs->anchor))) {
+ printf("pfctl_load_rulesets: "
+ "pfctl_ruleset_trans %d\n", error);
+ goto error;
}
- } else
+ } else if (pf->opts & PF_OPT_VERBOSE)
printf("\n");
+
}
if (pf->optimize && rs_num == PF_RULESET_FILTER)
pfctl_optimize_ruleset(pf, rs);
-
while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) {
TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries);
if ((error = pfctl_load_rule(pf, path, r, depth)))
@@ -1101,7 +1131,7 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs,
printf("\n");
free(r);
}
- if (brace) {
+ if (brace && pf->opts & PF_OPT_VERBOSE) {
INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
printf("}\n");
}
@@ -1118,28 +1148,49 @@ int
pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
{
u_int8_t rs_num = pf_get_ruleset_number(r->action);
+ char *name;
struct pfioc_rule pr;
+ int len = strlen(path);
+
+ bzero(&pr, sizeof(pr));
+ /* set up anchor before adding to path for anchor_call */
+ if ((pf->opts & PF_OPT_NOACTION) == 0)
+ pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path);
+ if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor))
+ errx(1, "pfctl_load_rule: strlcpy");
+
+ if (r->anchor) {
+ if (r->anchor->match) {
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len,
+ "/%s", r->anchor->name);
+ else
+ snprintf(&path[len], MAXPATHLEN - len,
+ "%s", r->anchor->name);
+ name = path;
+ } else
+ name = r->anchor->path;
+ } else
+ name = "";
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- bzero(&pr, sizeof(pr));
- if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >=
- sizeof(pr.anchor))
- errx(1, "pfctl_load_rule: strlcpy");
if (pfctl_add_pool(pf, &r->rpool, r->af))
return (1);
- pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path);
pr.pool_ticket = pf->paddr.ticket;
memcpy(&pr.rule, r, sizeof(pr.rule));
- if (r->anchor && strlcpy(pr.anchor_call, r->anchor->name,
- sizeof(pr.anchor_call)));
+ if (r->anchor && strlcpy(pr.anchor_call, name,
+ sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call))
+ errx(1, "pfctl_load_rule: strlcpy");
if (ioctl(pf->dev, DIOCADDRULE, &pr))
err(1, "DIOCADDRULE");
}
+
if (pf->opts & PF_OPT_VERBOSE) {
INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
print_rule(r, r->anchor ? r->anchor->name : "",
pf->opts & PF_OPT_VERBOSE2);
}
+ path[len] = '\0';
pfctl_clear_pool(&r->rpool);
return (0);
}
@@ -1208,8 +1259,21 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
pf.opts = opts;
pf.optimize = optimize;
pf.loadopt = loadopt;
- pf.anchor = pf_find_or_create_ruleset(anchorname)->anchor;
+
+ /* non-brace anchor, create without resolving the path */
+ if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
+ ERRX("pfctl_rules: calloc");
rs = &pf.anchor->ruleset;
+ pf_init_ruleset(rs);
+ rs->anchor = pf.anchor;
+ if (strlcpy(pf.anchor->path, anchorname,
+ sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
+ errx(1, "pfctl_add_rule: strlcpy");
+ if (strlcpy(pf.anchor->name, anchorname,
+ sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
+ errx(1, "pfctl_add_rule: strlcpy");
+
+
pf.astack[0] = pf.anchor;
pf.asd = 0;
if (anchorname[0])