summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormcbride <mcbride@openbsd.org>2007-05-08 23:31:20 +0000
committermcbride <mcbride@openbsd.org>2007-05-08 23:31:20 +0000
commit02de73e740e3713fa83a352dcc3cd15a6cd22216 (patch)
tree90c57115d89b1dd79ad81f8cbbb054fee0978518
parentKILL all IPv6 packets with the rthdr0 extension header or multiple routing (diff)
downloadwireguard-openbsd-02de73e740e3713fa83a352dcc3cd15a6cd22216.tar.xz
wireguard-openbsd-02de73e740e3713fa83a352dcc3cd15a6cd22216.zip
Routing headers are dangerous. Deal with them the same way as IPv4 options:
drop all packets with routing headers unless the matching rule explicitly specifies 'allow-opts'. ok dhartmei@ henning@ deraadt@ claudio@
-rw-r--r--sys/net/pf.c69
1 files changed, 20 insertions, 49 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 793dc341502..079680a5a20 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.527 2007/02/22 15:23:23 pyr Exp $ */
+/* $OpenBSD: pf.c,v 1.528 2007/05/08 23:31:20 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -6248,7 +6248,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, terminal = 0, dirndx;
+ int off, terminal = 0, dirndx, rh_cnt = 0;
if (!pf_status.running)
return (PF_PASS);
@@ -6327,61 +6327,24 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
goto done;
case IPPROTO_ROUTING: {
struct ip6_rthdr rthdr;
- struct ip6_rthdr0 rthdr0;
- struct in6_addr finaldst;
- struct ip6_hdr *ip6;
+ if (rh_cnt++) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 more than one rthdr\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ goto done;
+ }
if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
&reason, pd.af)) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: IPv6 short rthdr\n"));
action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
log = 1;
goto done;
}
- if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
- if (!pf_pull_hdr(m, off, &rthdr0,
- sizeof(rthdr0), NULL, &reason, pd.af)) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 short rthdr0\n"));
- action = PF_DROP;
- log = 1;
- goto done;
- }
- if (rthdr0.ip6r0_segleft != 0) {
- if (!pf_pull_hdr(m, off +
- sizeof(rthdr0) +
- rthdr0.ip6r0_len * 8 -
- sizeof(finaldst), &finaldst,
- sizeof(finaldst), NULL,
- &reason, pd.af)) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: IPv6 short rthdr0\n"));
- action = PF_DROP;
- log = 1;
- goto done;
- }
-
- n = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
- if (!n) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: mbuf shortage\n"));
- action = PF_DROP;
- log = 1;
- goto done;
- }
- n = m_pullup(n, sizeof(struct ip6_hdr));
- if (!n) {
- DPFPRINTF(PF_DEBUG_MISC,
- ("pf: mbuf shortage\n"));
- action = PF_DROP;
- log = 1;
- goto done;
- }
- ip6 = mtod(n, struct ip6_hdr *);
- ip6->ip6_dst = finaldst;
- }
- }
/* FALLTHROUGH */
}
case IPPROTO_AH:
@@ -6542,7 +6505,15 @@ done:
n = NULL;
}
- /* XXX handle IPv6 options, if not allowed. not implemented. */
+ /* handle dangerous IPv6 extension headers. */
+ if (action == PF_PASS && rh_cnt &&
+ !((s && s->allow_opts) || r->allow_opts)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: dropping packet with dangerous v6 headers\n"));
+ }
if ((s && s->tag) || r->rtableid)
pf_tag_packet(m, pd.pf_mtag, s ? s->tag : 0, r->rtableid);