diff options
author | kris <kris@FreeBSD.org> | 2001-01-23 21:11:28 +0000 |
---|---|---|
committer | kris <kris@FreeBSD.org> | 2001-01-23 21:11:28 +0000 |
commit | 1a36de8090ca93b96cbcf1600aa926043c3cd362 (patch) | |
tree | 6adb8641fcf32c14d75d28655a5a414d5d80a75a | |
parent | 6ebef802b2dd48f691c8cbe4426a1d3184748405 (diff) | |
download | FreeBSD-src-1a36de8090ca93b96cbcf1600aa926043c3cd362.zip FreeBSD-src-1a36de8090ca93b96cbcf1600aa926043c3cd362.tar.gz |
Fix the vulnerability with TCP ECE packets recently fixed in ipfw.
This is untested, but believed to work.
-rw-r--r-- | sbin/ip6fw/ip6fw.c | 4 | ||||
-rw-r--r-- | sys/netinet6/ip6_fw.c | 16 | ||||
-rw-r--r-- | sys/netinet6/ip6_fw.h | 7 |
3 files changed, 20 insertions, 7 deletions
diff --git a/sbin/ip6fw/ip6fw.c b/sbin/ip6fw/ip6fw.c index a25fed5..0c5b3b4 100644 --- a/sbin/ip6fw/ip6fw.c +++ b/sbin/ip6fw/ip6fw.c @@ -364,7 +364,7 @@ show_ip6fw(struct ip6_fw *chain) if (chain->fw_ip6nopt & IPV6_FW_IP6OPT_OPTS) PRINTOPT("!opts"); } - if (chain->fw_tcpf & IPV6_FW_TCPF_ESTAB) + if (chain->fw_ipflg & IPV6_FW_IF_TCPEST) printf(" established"); else if (chain->fw_tcpf == IPV6_FW_TCPF_SYN && chain->fw_tcpnf == IPV6_FW_TCPF_ACK) @@ -1060,7 +1060,7 @@ badviacombo: } if (rule.fw_prot == IPPROTO_TCP) { if (!strncmp(*av,"established",strlen(*av))) { - rule.fw_tcpf |= IPV6_FW_TCPF_ESTAB; + rule.fw_ipflg |= IPV6_FW_IF_TCPEST; av++; ac--; continue; } if (!strncmp(*av,"setup",strlen(*av))) { diff --git a/sys/netinet6/ip6_fw.c b/sys/netinet6/ip6_fw.c index bd50857..ae1c0f1 100644 --- a/sys/netinet6/ip6_fw.c +++ b/sys/netinet6/ip6_fw.c @@ -149,9 +149,15 @@ tcp6flg_match(struct tcphdr *tcp6, struct ip6_fw *f) { u_char flg_set, flg_clr; - if ((f->fw_tcpf & IPV6_FW_TCPF_ESTAB) && - (tcp6->th_flags & (IPV6_FW_TCPF_RST | IPV6_FW_TCPF_ACK))) - return 1; + /* + * If an established connection is required, reject packets that + * have only SYN of RST|ACK|SYN set. Otherwise, fall through to + * other flag requirements. + */ + if ((f->fw_ipflg & IPV6_FW_IF_TCPEST) && + ((tcp6->th_flags & (IPV6_FW_TCPF_RST | IPV6_FW_TCPF_ACK | + IPV6_FW_TCPF_SYN)) == IPV6_FW_TCPF_SYN)) + return 0; flg_set = tcp6->th_flags & f->fw_tcpf; flg_clr = tcp6->th_flags & f->fw_tcpnf; @@ -571,7 +577,9 @@ ip6_fw_chk(struct ip6_hdr **pip6, } PULLUP_TO(off + 14); tcp6 = (struct tcphdr *) ((caddr_t)ip6 + off); - if (f->fw_tcpf != f->fw_tcpnf && !tcp6flg_match(tcp6, f)) + if (((f->fw_tcpf != f->fw_tcpnf) || + (f->fw_ipflg & IPV6_FW_IF_TCPEST)) && + !tcp6flg_match(tcp6, f)) continue; src_port = ntohs(tcp6->th_sport); dst_port = ntohs(tcp6->th_dport); diff --git a/sys/netinet6/ip6_fw.h b/sys/netinet6/ip6_fw.h index 0418d18..bcd1a03 100644 --- a/sys/netinet6/ip6_fw.h +++ b/sys/netinet6/ip6_fw.h @@ -59,6 +59,7 @@ struct ip6_fw { u_short fw_number; /* Rule number */ u_short fw_flg; /* Flags word */ #define IPV6_FW_MAX_PORTS 10 /* A reasonable maximum */ + u_int fw_ipflg; /* IP flags word */ u_short fw_pts[IPV6_FW_MAX_PORTS]; /* Array of port numbers to match */ u_char fw_ip6opt,fw_ip6nopt; /* IPv6 options set/unset */ u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */ @@ -137,6 +138,11 @@ struct ip6_fw_chain { #define IPV6_FW_F_MASK 0xFFFF /* All possible flag bits mask */ +/* + * Flags for the 'fw_ipflg' field, for comparing values of ip and its protocols. */ +#define IPV6_FW_IF_TCPEST 0x00000020 /* established TCP connection */ +#define IPV6_FW_IF_TCPMSK 0x00000020 /* mask of all TCP values */ + /* * For backwards compatibility with rules specifying "via iface" but * not restricted to only "in" or "out" packets, we define this combination @@ -171,7 +177,6 @@ struct ip6_fw_chain { #define IPV6_FW_TCPF_PSH TH_PUSH #define IPV6_FW_TCPF_ACK TH_ACK #define IPV6_FW_TCPF_URG TH_URG -#define IPV6_FW_TCPF_ESTAB 0x40 /* * Main firewall chains definitions and global var's definitions. |