summaryrefslogtreecommitdiffstats
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorkn <kn@openbsd.org>2020-12-16 18:01:16 +0000
committerkn <kn@openbsd.org>2020-12-16 18:01:16 +0000
commit123a1e155c22c495116bca08e0d75db8b278a779 (patch)
tree85d79fddf6e2e23b1077a8bd05bb988c86277a34 /sbin/pfctl
parentReject rules with invalid port ranges (diff)
downloadwireguard-openbsd-123a1e155c22c495116bca08e0d75db8b278a779.tar.xz
wireguard-openbsd-123a1e155c22c495116bca08e0d75db8b278a779.zip
Fail to parse rules with invalid ranges
This makes pfctl(8) detect bogus ranges (with and without `-n') before loading the ruleset and completes the previous commit. OK sashan sthen
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/parse.y36
1 files changed, 33 insertions, 3 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 26027e3841b..2b3e62b1a7e 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.706 2020/12/16 18:00:44 kn Exp $ */
+/* $OpenBSD: parse.y,v 1.707 2020/12/16 18:01:16 kn Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -353,6 +353,7 @@ struct node_hfsc_opts hfsc_opts;
struct node_state_opt *keep_state_defaults = NULL;
struct pfctl_watermarks syncookie_opts;
+int validate_range(u_int8_t, u_int16_t, u_int16_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 *);
@@ -2892,9 +2893,15 @@ 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 = $$;
@@ -2926,6 +2933,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 = $$;
}
@@ -3932,6 +3943,19 @@ yyerror(const char *fmt, ...)
}
int
+validate_range(u_int8_t op, u_int16_t p1, u_int16_t p2)
+{
+ u_int16_t a = ntohs(p1);
+ u_int16_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)
@@ -4616,6 +4640,12 @@ apply_redirspec(struct pf_pool *rpool, struct pf_rule *r, struct redirspec *rs,
rpool->proxy_port[1] = ntohs(rs->rdr->rport.a) +
(ntohs(np->port[1]) - ntohs(np->port[0]));
} else {
+ if (validate_range(rs->rdr->rport.t, rs->rdr->rport.a,
+ rs->rdr->rport.b)) {
+ yyerror("invalid rdr-to port range");
+ return (1);
+ }
+
rpool->port_op = rs->rdr->rport.t;
rpool->proxy_port[1] = ntohs(rs->rdr->rport.b);
}