aboutsummaryrefslogtreecommitdiff
path: root/sbin/pfctl/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/pfctl/parse.y')
-rw-r--r--sbin/pfctl/parse.y101
1 files changed, 65 insertions, 36 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index af1fb95398f8..358fa909fc50 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -95,7 +95,7 @@ static struct file {
int eof_reached;
int lineno;
int errors;
-} *file;
+} *file, *topfile;
struct file *pushfile(const char *, int);
int popfile(void);
int check_file_secrecy(int, const char *);
@@ -367,6 +367,7 @@ static struct node_fairq_opts fairq_opts;
static struct node_state_opt *keep_state_defaults = NULL;
static struct pfctl_watermarks syncookie_opts;
+int validate_range(uint8_t, uint16_t, uint16_t);
int disallow_table(struct node_host *, const char *);
int disallow_urpf_failed(struct node_host *, const char *);
int disallow_alias(struct node_host *, const char *);
@@ -3231,8 +3232,7 @@ logopts : logopt { $$ = $1; }
logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
| MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; }
- | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
- | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
+ | USER { $$.log = PF_LOG_USER; $$.logif = 0; }
| TO string {
const char *errstr;
u_int i;
@@ -3825,9 +3825,14 @@ port_item : portrange {
err(1, "port_item: calloc");
$$->port[0] = $1.a;
$$->port[1] = $1.b;
- if ($1.t)
+ if ($1.t) {
$$->op = PF_OP_RRG;
- else
+ if (validate_range($$->op, $$->port[0],
+ $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
+ } else
$$->op = PF_OP_EQ;
$$->next = NULL;
$$->tail = $$;
@@ -3844,6 +3849,10 @@ port_item : portrange {
$$->port[0] = $2.a;
$$->port[1] = $2.b;
$$->op = $1;
+ if (validate_range($$->op, $$->port[0], $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
$$->next = NULL;
$$->tail = $$;
}
@@ -3859,6 +3868,10 @@ port_item : portrange {
$$->port[0] = $1.a;
$$->port[1] = $3.a;
$$->op = $2;
+ if (validate_range($$->op, $$->port[0], $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
$$->next = NULL;
$$->tail = $$;
}
@@ -3905,7 +3918,7 @@ uid_item : uid {
$$->tail = $$;
}
| unaryop uid {
- if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
+ if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
yyerror("user unknown requires operator = or "
"!=");
YYERROR;
@@ -3920,7 +3933,7 @@ uid_item : uid {
$$->tail = $$;
}
| uid PORTBINARY uid {
- if ($1 == UID_MAX || $3 == UID_MAX) {
+ if ($1 == -1 || $3 == -1) {
yyerror("user unknown requires operator = or "
"!=");
YYERROR;
@@ -3938,7 +3951,7 @@ uid_item : uid {
uid : STRING {
if (!strcmp($1, "unknown"))
- $$ = UID_MAX;
+ $$ = -1;
else {
uid_t uid;
@@ -3983,7 +3996,7 @@ gid_item : gid {
$$->tail = $$;
}
| unaryop gid {
- if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
+ if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
yyerror("group unknown requires operator = or "
"!=");
YYERROR;
@@ -3998,7 +4011,7 @@ gid_item : gid {
$$->tail = $$;
}
| gid PORTBINARY gid {
- if ($1 == GID_MAX || $3 == GID_MAX) {
+ if ($1 == -1 || $3 == -1) {
yyerror("group unknown requires operator = or "
"!=");
YYERROR;
@@ -4016,7 +4029,7 @@ gid_item : gid {
gid : STRING {
if (!strcmp($1, "unknown"))
- $$ = GID_MAX;
+ $$ = -1;
else {
gid_t gid;
@@ -5197,6 +5210,19 @@ yyerror(const char *fmt, ...)
}
int
+validate_range(uint8_t op, uint16_t p1, uint16_t p2)
+{
+ uint16_t a = ntohs(p1);
+ uint16_t b = ntohs(p2);
+
+ if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
+ (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
+ (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
+ return 1;
+ return 0;
+}
+
+int
disallow_table(struct node_host *h, const char *fmt)
{
for (; h != NULL; h = h->next)
@@ -5324,6 +5350,10 @@ filter_consistent(struct pfctl_rule *r, int anchor_call)
"synproxy state or modulate state");
problems++;
}
+ if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN))
+ fprintf(stderr, "%s:%d: warning: "
+ "synproxy used for inbound rules only, "
+ "ignored for outbound\n", file->name, yylval.lineno);
if (r->rule_flag & PFRULE_AFTO && r->rt) {
if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) {
yyerror("dup-to "
@@ -5458,7 +5488,7 @@ process_tabledef(char *name, struct table_opts *opts, int popts)
name);
else
yyerror("cannot define table %s: %s", name,
- pfr_strerror(errno));
+ pf_strerror(errno));
goto _error;
}
@@ -6014,8 +6044,14 @@ apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec
if (!rs->rport.b && rs->rport.t) {
rpool->proxy_port[1] = ntohs(rs->rport.a) +
(ntohs(r->dst.port[1]) - ntohs(r->dst.port[0]));
- } else
+ } else {
+ if (validate_range(rs->rport.t, rs->rport.a,
+ rs->rport.b)) {
+ yyerror("invalid rdr-to port range");
+ return (1);
+ }
r->rdr.proxy_port[1] = ntohs(rs->rport.b);
+ }
if (rs->pool_opts.staticport) {
yyerror("the 'static-port' option is only valid with nat rules");
@@ -6743,7 +6779,7 @@ lgetc(int quotec)
if (quotec) {
if ((c = igetc()) == EOF) {
yyerror("reached end of file while parsing quoted string");
- if (popfile() == EOF)
+ if (file == topfile || popfile() == EOF)
return (EOF);
return (quotec);
}
@@ -6771,7 +6807,7 @@ lgetc(int quotec)
return ('\n');
}
while (c == EOF) {
- if (popfile() == EOF)
+ if (file == topfile || popfile() == EOF)
return (EOF);
c = igetc();
}
@@ -7069,17 +7105,17 @@ popfile(void)
{
struct file *prev;
- if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
prev->errors += file->errors;
- TAILQ_REMOVE(&files, file, entry);
- fclose(file->stream);
- free(file->name);
- free(file->ungetbuf);
- free(file);
- file = prev;
- return (0);
- }
- return (EOF);
+
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file->ungetbuf);
+ free(file);
+ file = prev;
+
+ return (file ? 0 : EOF);
}
int
@@ -7102,6 +7138,7 @@ parse_config(char *filename, struct pfctl *xpf)
warn("cannot open the main config file!");
return (-1);
}
+ topfile = file;
yyparse();
errors = file->errors;
@@ -7201,19 +7238,11 @@ mv_rules(struct pfctl_ruleset *src, struct pfctl_ruleset *dst)
struct pfctl_rule *r;
for (i = 0; i < PF_RULESET_MAX; ++i) {
- while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
- != NULL) {
- TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
- TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
+ TAILQ_FOREACH(r, src->rules[i].active.ptr, entries)
dst->anchor->match++;
- }
+ TAILQ_CONCAT(dst->rules[i].active.ptr, src->rules[i].active.ptr, entries);
src->anchor->match = 0;
- while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
- != NULL) {
- TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
- TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
- r, entries);
- }
+ TAILQ_CONCAT(dst->rules[i].inactive.ptr, src->rules[i].inactive.ptr, entries);
}
}