diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in_pcb.c | 14 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 38 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 101 | ||||
-rw-r--r-- | sys/netinet/ip_ipsec.c | 249 | ||||
-rw-r--r-- | sys/netinet/ip_ipsec.h | 40 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 66 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 11 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 28 | ||||
-rw-r--r-- | sys/netinet/sctp_os_bsd.h | 10 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 18 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 116 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 67 | ||||
-rw-r--r-- | sys/netinet/tcp_stacks/fastpath.c | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 369 | ||||
-rw-r--r-- | sys/netinet/tcp_syncache.c | 149 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 30 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 30 | ||||
-rw-r--r-- | sys/netinet/udp.h | 2 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 224 |
19 files changed, 311 insertions, 1257 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 7d5da0e..7eb48af 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -96,11 +96,7 @@ __FBSDID("$FreeBSD$"); #include <netinet6/ip6_var.h> #endif /* INET6 */ - -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/key.h> -#endif /* IPSEC */ +#include <netipsec/ipsec_support.h> #include <security/mac/mac_framework.h> @@ -303,8 +299,8 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) goto out; mac_inpcb_create(so, inp); #endif -#ifdef IPSEC - error = ipsec_init_policy(so, &inp->inp_sp); +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + error = ipsec_init_pcbpolicy(inp); if (error != 0) { #ifdef MAC mac_inpcb_destroy(inp); @@ -331,7 +327,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) inp->inp_gencnt = ++pcbinfo->ipi_gencnt; refcount_init(&inp->inp_refcount, 1); /* Reference from inpcbinfo */ INP_LIST_WUNLOCK(pcbinfo); -#if defined(IPSEC) || defined(MAC) +#if defined(IPSEC) || defined(IPSEC_SUPPORT) || defined(MAC) out: if (error != 0) { crfree(inp->inp_cred); @@ -1278,7 +1274,7 @@ in_pcbfree(struct inpcb *inp) INP_WLOCK_ASSERT(inp); /* XXXRW: Do as much as possible here. */ -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) if (inp->inp_sp != NULL) ipsec_delete_pcbpolicy(inp); #endif diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 7403ec0..363716f 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -90,10 +90,6 @@ __FBSDID("$FreeBSD$"); static struct pr_usrreqs nousrreqs; -#ifdef IPSEC -#include <netipsec/ipsec.h> -#endif /* IPSEC */ - #ifdef SCTP #include <netinet/in_pcb.h> #include <netinet/sctp_pcb.h> @@ -152,7 +148,7 @@ struct protosw inetsw[] = { .pr_type = SOCK_SEQPACKET, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_SCTP, - .pr_flags = PR_WANTRCVD, + .pr_flags = PR_WANTRCVD|PR_LASTHDR, .pr_input = sctp_input, .pr_ctlinput = sctp_ctlinput, .pr_ctloutput = sctp_ctloutput, @@ -164,7 +160,7 @@ struct protosw inetsw[] = { .pr_type = SOCK_STREAM, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_SCTP, - .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR, .pr_input = sctp_input, .pr_ctlinput = sctp_ctlinput, .pr_ctloutput = sctp_ctloutput, @@ -222,34 +218,6 @@ struct protosw inetsw[] = { .pr_ctloutput = rip_ctloutput, .pr_usrreqs = &rip_usrreqs }, -#ifdef IPSEC -{ - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_AH, - .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = ah4_input, - .pr_ctlinput = ah4_ctlinput, - .pr_usrreqs = &nousrreqs -}, -{ - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_ESP, - .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = esp4_input, - .pr_ctlinput = esp4_ctlinput, - .pr_usrreqs = &nousrreqs -}, -{ - .pr_type = SOCK_RAW, - .pr_domain = &inetdomain, - .pr_protocol = IPPROTO_IPCOMP, - .pr_flags = PR_ATOMIC|PR_ADDR, - .pr_input = ipcomp4_input, - .pr_usrreqs = &nousrreqs -}, -#endif /* IPSEC */ { .pr_type = SOCK_RAW, .pr_domain = &inetdomain, @@ -366,7 +334,7 @@ SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP"); SYSCTL_NODE(_net_inet, IPPROTO_SCTP, sctp, CTLFLAG_RW, 0, "SCTP"); #endif SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP"); -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* XXX no protocol # to use, pick something "reserved" */ SYSCTL_NODE(_net_inet, 253, ipsec, CTLFLAG_RW, 0, "IPSEC"); SYSCTL_NODE(_net_inet, IPPROTO_AH, ah, CTLFLAG_RW, 0, "AH"); diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 73a155d..9f2b7df 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -77,13 +77,10 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_options.h> #include <machine/in_cksum.h> #include <netinet/ip_carp.h> -#ifdef IPSEC -#include <netinet/ip_ipsec.h> -#include <netipsec/ipsec.h> -#include <netipsec/key.h> -#endif /* IPSEC */ #include <netinet/in_rss.h> +#include <netipsec/ipsec_support.h> + #include <sys/socketvar.h> #include <security/mac/mac_framework.h> @@ -430,6 +427,12 @@ ip_direct_input(struct mbuf *m) ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + if (IPSEC_ENABLED(ipv4)) { + if (IPSEC_INPUT(ipv4, m, hlen, ip->ip_p) != 0) + return; + } +#endif /* IPSEC */ IPSTAT_INC(ips_delivered); (*inetsw[ip_protox[ip->ip_p]].pr_input)(&m, &hlen, ip->ip_p); return; @@ -559,11 +562,11 @@ tooshort: * ip pointer. */ if (V_ipforwarding != 0 -#ifdef IPSEC - && !key_havesp(IPSEC_DIR_INBOUND) - && !key_havesp(IPSEC_DIR_OUTBOUND) +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + && (!IPSEC_ENABLED(ipv4) || + IPSEC_CAPS(ipv4, m, IPSEC_CAP_OPERABLE) == 0) #endif - ) { + ) { if ((m = ip_tryforward(m)) == NULL) return; if (m->m_flags & M_FASTFWD_OURS) { @@ -572,13 +575,16 @@ tooshort: goto ours; } } -#ifdef IPSEC + +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* * Bypass packet filtering for packets previously handled by IPsec. */ - if (ip_ipsec_filtertunnel(m)) - goto passin; + if (IPSEC_ENABLED(ipv4) && + IPSEC_CAPS(ipv4, m, IPSEC_CAP_BYPASS_FILTER) != 0) + goto passin; #endif + /* * Run through list of hooks for input packets. * @@ -802,14 +808,11 @@ ours: hlen = ip->ip_hl << 2; } -#ifdef IPSEC - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if (ip_ipsec_input(m, ip->ip_p) != 0) - goto bad; +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + if (IPSEC_ENABLED(ipv4)) { + if (IPSEC_INPUT(ipv4, m, hlen, ip->ip_p) != 0) + return; + } #endif /* IPSEC */ /* @@ -951,24 +954,14 @@ ip_forward(struct mbuf *m, int srcrt) m_freem(m); return; } -#ifdef IPSEC - if (ip_ipsec_fwd(m) != 0) { - IPSTAT_INC(ips_cantforward); - m_freem(m); - return; - } -#endif /* IPSEC */ + if ( #ifdef IPSTEALTH - if (!V_ipstealth) { + V_ipstealth == 0 && #endif - if (ip->ip_ttl <= IPTTLDEC) { - icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, - 0, 0); - return; - } -#ifdef IPSTEALTH + ip->ip_ttl <= IPTTLDEC) { + icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, 0); + return; } -#endif bzero(&ro, sizeof(ro)); sin = (struct sockaddr_in *)&ro.ro_dst; @@ -987,19 +980,6 @@ ip_forward(struct mbuf *m, int srcrt) ifa_ref(&ia->ia_ifa); } else ia = NULL; -#ifndef IPSEC - /* - * 'ia' may be NULL if there is no route for this destination. - * In case of IPsec, Don't discard it just yet, but pass it to - * ip_output in case of outgoing IPsec policy. - */ - if (!srcrt && ia == NULL) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); - RO_RTFREE(&ro); - return; - } -#endif - /* * Save the IP header and at most 8 bytes of the payload, * in case we need to generate an ICMP message to the src. @@ -1032,15 +1012,22 @@ ip_forward(struct mbuf *m, int srcrt) mcopy->m_pkthdr.len = mcopy->m_len; m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t)); } - #ifdef IPSTEALTH - if (!V_ipstealth) { + if (V_ipstealth == 0) #endif ip->ip_ttl -= IPTTLDEC; -#ifdef IPSTEALTH +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + if (IPSEC_ENABLED(ipv4)) { + if ((error = IPSEC_FORWARD(ipv4, m)) != 0) { + /* mbuf consumed by IPsec */ + m_freem(mcopy); + if (error != EINPROGRESS) + IPSTAT_INC(ips_cantforward); + return; + } + /* No IPsec processing required */ } -#endif - +#endif /* IPSEC */ /* * If forwarding packet using same interface that it came in on, * perhaps should send a redirect to sender to shortcut a hop. @@ -1118,14 +1105,6 @@ ip_forward(struct mbuf *m, int srcrt) case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; - -#ifdef IPSEC - /* - * If IPsec is configured for this path, - * override any possibly mtu value set by ip_output. - */ - mtu = ip_ipsec_mtu(mcopy, mtu); -#endif /* IPSEC */ /* * If the MTU was set before make sure we are below the * interface MTU. diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c deleted file mode 100644 index ac1e3d5..0000000 --- a/sys/netinet/ip_ipsec.c +++ /dev/null @@ -1,249 +0,0 @@ -/*- - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_ipsec.h" -#include "opt_sctp.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/errno.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/vnet.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/ip_var.h> -#include <netinet/ip_options.h> -#include <netinet/ip_ipsec.h> -#ifdef SCTP -#include <netinet/sctp_crc32.h> -#endif - -#include <machine/in_cksum.h> - -#include <netipsec/ipsec.h> -#include <netipsec/xform.h> -#include <netipsec/key.h> - -extern struct protosw inetsw[]; - -#ifdef IPSEC_FILTERTUNNEL -static VNET_DEFINE(int, ip4_ipsec_filtertunnel) = 1; -#else -static VNET_DEFINE(int, ip4_ipsec_filtertunnel) = 0; -#endif -#define V_ip4_ipsec_filtertunnel VNET(ip4_ipsec_filtertunnel) - -SYSCTL_DECL(_net_inet_ipsec); -SYSCTL_INT(_net_inet_ipsec, OID_AUTO, filtertunnel, - CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_filtertunnel), 0, - "If set filter packets from an IPsec tunnel."); - -/* - * Check if we have to jump over firewall processing for this packet. - * Called from ip_input(). - * 1 = jump over firewall, 0 = packet goes through firewall. - */ -int -ip_ipsec_filtertunnel(struct mbuf *m) -{ - - /* - * Bypass packet filtering for packets previously handled by IPsec. - */ - if (!V_ip4_ipsec_filtertunnel && - m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL) - return 1; - return 0; -} - -/* - * Check if this packet has an active SA and needs to be dropped instead - * of forwarded. - * Called from ip_forward(). - * 1 = drop packet, 0 = forward packet. - */ -int -ip_ipsec_fwd(struct mbuf *m) -{ - - return (ipsec4_in_reject(m, NULL)); -} - -/* - * Check if protocol type doesn't have a further header and do IPSEC - * decryption or reject right now. Protocols with further headers get - * their IPSEC treatment within the protocol specific processing. - * Called from ip_input(). - * 1 = drop packet, 0 = continue processing packet. - */ -int -ip_ipsec_input(struct mbuf *m, int nxt) -{ - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0) - return (ipsec4_in_reject(m, NULL)); - return (0); -} - -/* - * Compute the MTU for a forwarded packet that gets IPSEC encapsulated. - * Called from ip_forward(). - * Returns MTU suggestion for ICMP needfrag reply. - */ -int -ip_ipsec_mtu(struct mbuf *m, int mtu) -{ - /* - * If the packet is routed over IPsec tunnel, tell the - * originator the tunnel MTU. - * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz - * XXX quickhack!!! - */ - return (mtu - ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL)); -} - -/* - * - * Called from ip_output(). - * 1 = drop packet, 0 = continue processing packet, - * -1 = packet was reinjected and stop processing packet - */ -int -ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error) -{ - struct secpolicy *sp; - - if (!key_havesp(IPSEC_DIR_OUTBOUND)) - return 0; - - /* - * Check the security policy (SP) for the packet and, if - * required, do IPsec-related processing. There are two - * cases here; the first time a packet is sent through - * it will be untagged and handled by ipsec4_checkpolicy. - * If the packet is resubmitted to ip_output (e.g. after - * AH, ESP, etc. processing), there will be a tag to bypass - * the lookup and related policy checking. - */ - if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) { - *error = 0; - return (0); - } - sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp); - /* - * There are four return cases: - * sp != NULL apply IPsec policy - * sp == NULL, error == 0 no IPsec handling needed - * sp == NULL, error == -EINVAL discard packet w/o error - * sp == NULL, error != 0 discard packet, report error - */ - if (sp != NULL) { - /* - * Do delayed checksums now because we send before - * this is done in the normal processing path. - */ - if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(*m); - (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; - } -#ifdef SCTP - if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) { - struct ip *ip = mtod(*m, struct ip *); - - sctp_delayed_cksum(*m, (uint32_t)(ip->ip_hl << 2)); - (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP; - } -#endif - - /* NB: callee frees mbuf */ - *error = ipsec4_process_packet(*m, sp->req); - KEY_FREESP(&sp); - if (*error == EJUSTRETURN) { - /* - * We had a SP with a level of 'use' and no SA. We - * will just continue to process the packet without - * IPsec processing and return without error. - */ - *error = 0; - goto done; - } - /* - * Preserve KAME behaviour: ENOENT can be returned - * when an SA acquire is in progress. Don't propagate - * this to user-level; it confuses applications. - * - * XXX this will go away when the SADB is redone. - */ - if (*error == ENOENT) - *error = 0; - goto reinjected; - } else { /* sp == NULL */ - - if (*error != 0) { - /* - * Hack: -EINVAL is used to signal that a packet - * should be silently discarded. This is typically - * because we asked key management for an SA and - * it was delayed (e.g. kicked up to IKE). - */ - if (*error == -EINVAL) - *error = 0; - goto bad; - } - /* No IPsec processing for this packet. */ - } -done: - return (0); -reinjected: - return (-1); -bad: - if (sp != NULL) - KEY_FREESP(&sp); - return 1; -} diff --git a/sys/netinet/ip_ipsec.h b/sys/netinet/ip_ipsec.h deleted file mode 100644 index f499b74..0000000 --- a/sys/netinet/ip_ipsec.h +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 1982, 1986, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _NETINET_IP_IPSEC_H_ -#define _NETINET_IP_IPSEC_H_ - -int ip_ipsec_filtertunnel(struct mbuf *); -int ip_ipsec_fwd(struct mbuf *); -int ip_ipsec_input(struct mbuf *, int); -int ip_ipsec_mtu(struct mbuf *, int); -int ip_ipsec_output(struct mbuf **, struct inpcb *, int *); -#endif diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index b1564a2..7b59b72 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -83,10 +83,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_crc32.h> #endif -#ifdef IPSEC -#include <netinet/ip_ipsec.h> -#include <netipsec/ipsec.h> -#endif /* IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> @@ -227,7 +224,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct rtentry *rte; /* cache for ro->ro_rt */ uint32_t fibnum; int have_ia_ref; -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) int no_route_but_check_spd = 0; #endif M_ASSERTPKTHDR(m); @@ -382,7 +379,7 @@ again: (rte->rt_flags & RTF_UP) == 0 || rte->rt_ifp == NULL || !RT_LINK_IS_UP(rte->rt_ifp)) { -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* * There is no route for this packet, but it is * possible that a matching SPD entry exists. @@ -552,15 +549,13 @@ again: } sendit: -#ifdef IPSEC - switch(ip_ipsec_output(&m, inp, &error)) { - case 1: - goto bad; - case -1: - goto done; - case 0: - default: - break; /* Continue with packet processing. */ +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + if (IPSEC_ENABLED(ipv4)) { + if ((error = IPSEC_OUTPUT(ipv4, m, inp)) != 0) { + if (error == EINPROGRESS) + error = 0; + goto done; + } } /* * Check if there was a route for this packet; return error if not. @@ -1190,23 +1185,13 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) INP_WUNLOCK(inp); break; -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) case IP_IPSEC_POLICY: - { - caddr_t req; - struct mbuf *m; - - if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */ + if (IPSEC_ENABLED(ipv4)) { + error = IPSEC_PCBCTL(ipv4, inp, sopt); break; - if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ - break; - req = mtod(m, caddr_t); - error = ipsec_set_policy(inp, sopt->sopt_name, req, - m->m_len, (sopt->sopt_td != NULL) ? - sopt->sopt_td->td_ucred : NULL); - m_freem(m); - break; - } + } + /* FALLTHROUGH */ #endif /* IPSEC */ default: @@ -1349,24 +1334,13 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) error = inp_getmoptions(inp, sopt); break; -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) case IP_IPSEC_POLICY: - { - struct mbuf *m = NULL; - caddr_t req = NULL; - size_t len = 0; - - if (m != NULL) { - req = mtod(m, caddr_t); - len = m->m_len; + if (IPSEC_ENABLED(ipv4)) { + error = IPSEC_PCBCTL(ipv4, inp, sopt); + break; } - error = ipsec_get_policy(sotoinpcb(so), req, len, &m); - if (error == 0) - error = soopt_mcopyout(sopt, m); /* XXX */ - if (error == 0) - m_freem(m); - break; - } + /* FALLTHROUGH */ #endif /* IPSEC */ default: diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 6d40954..661bbf4 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -73,9 +73,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_mroute.h> #include <netinet/ip_icmp.h> -#ifdef IPSEC -#include <netipsec/ipsec.h> -#endif /*IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/stdarg.h> #include <security/mac/mac_framework.h> @@ -236,10 +234,11 @@ rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n, INP_LOCK_ASSERT(last); -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* check AH/ESP integrity. */ - if (ipsec4_in_reject(n, last)) { - policyfail = 1; + if (IPSEC_ENABLED(ipv4)) { + if (IPSEC_CHECK_POLICY(ipv4, n, last) != 0) + policyfail = 1; } #endif /* IPSEC */ #ifdef MAC diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 5aa56ba..956b159 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -5790,34 +5790,6 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } else if (stcb == NULL) { inp_decr = inp; } -#ifdef IPSEC - /*- - * I very much doubt any of the IPSEC stuff will work but I have no - * idea, so I will leave it in place. - */ - if (inp != NULL) { - switch (dst->sa_family) { -#ifdef INET - case AF_INET: - if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { - SCTP_STAT_INCR(sctps_hdrops); - goto out; - } - break; -#endif -#ifdef INET6 - case AF_INET6: - if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { - SCTP_STAT_INCR(sctps_hdrops); - goto out; - } - break; -#endif - default: - break; - } - } -#endif SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", (void *)m, iphlen, offset, length, (void *)stcb); if (stcb) { diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index b0c92da..b439b59 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); /* * includes */ -#include "opt_ipsec.h" #include "opt_compat.h" #include "opt_inet6.h" #include "opt_inet.h" @@ -82,16 +81,8 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_icmp.h> #include <netinet/icmp_var.h> -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/key.h> -#endif /* IPSEC */ - #ifdef INET6 #include <sys/domain.h> -#ifdef IPSEC -#include <netipsec/ipsec6.h> -#endif #include <netinet/ip6.h> #include <netinet6/ip6_var.h> #include <netinet6/in6_pcb.h> @@ -100,7 +91,6 @@ __FBSDID("$FreeBSD$"); #include <netinet6/scope6_var.h> #endif /* INET6 */ - #include <netinet/ip_options.h> #include <crypto/sha1.h> diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index ffc3a7e..db3f39c 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -2469,15 +2469,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_INP_INFO_WUNLOCK(); return (ENOBUFS); } -#ifdef IPSEC - error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp); - if (error != 0) { - crfree(inp->ip_inp.inp.inp_cred); - SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); - SCTP_INP_INFO_WUNLOCK(); - return error; - } -#endif /* IPSEC */ SCTP_INCR_EP_COUNT(); inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl); SCTP_INP_INFO_WUNLOCK(); @@ -2504,9 +2495,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); so->so_pcb = NULL; crfree(inp->ip_inp.inp.inp_cred); -#ifdef IPSEC - ipsec_delete_pcbpolicy(&inp->ip_inp.inp); -#endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); } @@ -2527,9 +2515,6 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); so->so_pcb = NULL; crfree(inp->ip_inp.inp.inp_cred); -#ifdef IPSEC - ipsec_delete_pcbpolicy(&inp->ip_inp.inp); -#endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); } @@ -3641,9 +3626,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) * macro here since le_next will get freed as part of the * sctp_free_assoc() call. */ -#ifdef IPSEC - ipsec_delete_pcbpolicy(ip_pcb); -#endif if (ip_pcb->inp_options) { (void)sctp_m_free(ip_pcb->inp_options); ip_pcb->inp_options = 0; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index de71c31..3c6e604 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -118,10 +118,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/tcp_offload.h> #endif -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/ipsec6.h> -#endif /*IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> @@ -474,20 +471,6 @@ cc_post_recovery(struct tcpcb *tp, struct tcphdr *th) tp->t_bytes_acked = 0; } -#ifdef TCP_SIGNATURE -static inline int -tcp_signature_verify_input(struct mbuf *m, int off0, int tlen, int optlen, - struct tcpopt *to, struct tcphdr *th, u_int tcpbflag) -{ - int ret; - - tcp_fields_to_net(th); - ret = tcp_signature_verify(m, off0, tlen, optlen, to, th, tcpbflag); - tcp_fields_to_host(th); - return (ret); -} -#endif - /* * Indicate whether this ack should be delayed. We can delay the ack if * following conditions are met: @@ -598,9 +581,6 @@ tcp_input(struct mbuf **mp, int *offp, int proto) int drop_hdrlen; int thflags; int rstreason = 0; /* For badport_bandlim accounting purposes */ -#ifdef TCP_SIGNATURE - uint8_t sig_checked = 0; -#endif uint8_t iptos; struct m_tag *fwd_tag = NULL; #ifdef INET6 @@ -931,15 +911,22 @@ findpcb: inp->inp_flowid = m->m_pkthdr.flowid; inp->inp_flowtype = M_HASHTYPE_GET(m); } -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) #ifdef INET6 - if (isipv6 && ipsec6_in_reject(m, inp)) { + if (isipv6 && IPSEC_ENABLED(ipv6) && + IPSEC_CHECK_POLICY(ipv6, m, inp) != 0) { goto dropunlock; - } else + } +#ifdef INET + else +#endif #endif /* INET6 */ - if (ipsec4_in_reject(m, inp) != 0) { +#ifdef INET + if (IPSEC_ENABLED(ipv4) && + IPSEC_CHECK_POLICY(ipv4, m, inp) != 0) { goto dropunlock; } +#endif /* INET */ #endif /* IPSEC */ /* @@ -1122,7 +1109,16 @@ relocked: * NB: syncache_expand() doesn't unlock * inp and tcpinfo locks. */ - if (!syncache_expand(&inc, &to, th, &so, m)) { + rstreason = syncache_expand(&inc, &to, th, &so, m); + if (rstreason < 0) { + /* + * A failing TCP MD5 signature comparison + * must result in the segment being dropped + * and must not produce any response back + * to the sender. + */ + goto dropunlock; + } else if (rstreason == 0) { /* * No syncache entry or ACK was not * for our SYN/ACK. Send a RST. @@ -1174,26 +1170,6 @@ new_tfo_socket: tp = intotcpcb(inp); KASSERT(tp->t_state == TCPS_SYN_RECEIVED, ("%s: ", __func__)); -#ifdef TCP_SIGNATURE - if (sig_checked == 0) { - tcp_dooptions(&to, optp, optlen, - (thflags & TH_SYN) ? TO_SYN : 0); - if (!tcp_signature_verify_input(m, off0, tlen, - optlen, &to, th, tp->t_flags)) { - - /* - * In SYN_SENT state if it receives an - * RST, it is allowed for further - * processing. - */ - if ((thflags & TH_RST) == 0 || - (tp->t_state == TCPS_SYN_SENT) == 0) - goto dropunlock; - } - sig_checked = 1; - } -#endif - /* * Process the segment and the data it * contains. tcp_do_segment() consumes @@ -1423,26 +1399,18 @@ new_tfo_socket: */ goto dropunlock; } - -#ifdef TCP_SIGNATURE - if (sig_checked == 0) { - tcp_dooptions(&to, optp, optlen, - (thflags & TH_SYN) ? TO_SYN : 0); - if (!tcp_signature_verify_input(m, off0, tlen, optlen, &to, - th, tp->t_flags)) { - - /* - * In SYN_SENT state if it receives an RST, it is - * allowed for further processing. - */ - if ((thflags & TH_RST) == 0 || - (tp->t_state == TCPS_SYN_SENT) == 0) - goto dropunlock; +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + if (tp->t_flags & TF_SIGNATURE) { + tcp_dooptions(&to, optp, optlen, thflags); + if ((to.to_flags & TOF_SIGNATURE) == 0) { + TCPSTAT_INC(tcps_sig_err_nosigopt); + goto dropunlock; } - sig_checked = 1; + if (!TCPMD5_ENABLED() || + TCPMD5_INPUT(m, th, to.to_signature) != 0) + goto dropunlock; } #endif - TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th); /* @@ -1617,6 +1585,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, (th->th_off << 2) - sizeof(struct tcphdr), (thflags & TH_SYN) ? TO_SYN : 0); +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + if ((tp->t_flags & TF_SIGNATURE) != 0 && + (to.to_flags & TOF_SIGNATURE) == 0) { + TCPSTAT_INC(tcps_sig_err_sigopt); + /* XXX: should drop? */ + } +#endif /* * If echoed timestamp is later than the current time, * fall back to non RFC1323 RTT calculation. Normalize @@ -3378,20 +3353,19 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags) (char *)&to->to_tsecr, sizeof(to->to_tsecr)); to->to_tsecr = ntohl(to->to_tsecr); break; -#ifdef TCP_SIGNATURE - /* - * XXX In order to reply to a host which has set the - * TCP_SIGNATURE option in its initial SYN, we have to - * record the fact that the option was observed here - * for the syncache code to perform the correct response. - */ case TCPOPT_SIGNATURE: + /* + * In order to reply to a host which has set the + * TCP_SIGNATURE option in its initial SYN, we have + * to record the fact that the option was observed + * here for the syncache code to perform the correct + * response. + */ if (optlen != TCPOLEN_SIGNATURE) continue; to->to_flags |= TOF_SIGNATURE; to->to_signature = cp + 2; break; -#endif case TCPOPT_SACK_PERMITTED: if (optlen != TCPOLEN_SACK_PERMITTED) continue; diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 6519f99..adb46d3 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -88,9 +88,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/tcp_offload.h> #endif -#ifdef IPSEC -#include <netipsec/ipsec.h> -#endif /*IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> @@ -193,7 +191,7 @@ tcp_output(struct tcpcb *tp) struct tcphdr *th; u_char opt[TCP_MAXOLEN]; unsigned ipoptlen, optlen, hdrlen; -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) unsigned ipsec_optlen = 0; #endif int idle, sendalot; @@ -545,14 +543,23 @@ after_sack_rexmit: * the right thing below to provide length of just ip options and thus * checking for ipoptlen is enough to decide if ip options are present. */ -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* * Pre-calculate here as we save another lookup into the darknesses * of IPsec that way and can actually decide if TSO is ok. */ - ipsec_optlen = ipsec_hdrsiz_tcp(tp); +#ifdef INET6 + if (isipv6 && IPSEC_ENABLED(ipv6)) + ipsec_optlen = IPSEC_HDRSIZE(ipv6, tp->t_inpcb); +#ifdef INET + else #endif - +#endif /* INET6 */ +#ifdef INET + if (IPSEC_ENABLED(ipv4)) + ipsec_optlen = IPSEC_HDRSIZE(ipv4, tp->t_inpcb); +#endif /* INET */ +#endif /* IPSEC */ #ifdef INET6 if (isipv6) ipoptlen = ip6_optlen(tp->t_inpcb); @@ -563,7 +570,7 @@ after_sack_rexmit: offsetof(struct ipoption, ipopt_list); else ipoptlen = 0; -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) ipoptlen += ipsec_optlen; #endif @@ -831,8 +838,12 @@ send: to.to_sacks = (u_char *)tp->sackblks; } } -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) /* TCP-MD5 (RFC2385). */ + /* + * Check that TCP_MD5SIG is enabled in tcpcb to + * account the size needed to set this TCP option. + */ if (tp->t_flags & TF_SIGNATURE) to.to_flags |= TOF_SIGNATURE; #endif /* TCP_SIGNATURE */ @@ -1245,20 +1256,31 @@ send: */ tp->snd_up = tp->snd_una; /* drag it along */ -#ifdef TCP_SIGNATURE - if (to.to_flags & TOF_SIGNATURE) { - int sigoff = to.to_signature - opt; - tcp_signature_compute(m, 0, len, optlen, - (u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND); - } -#endif - /* * Put TCP length in extended header, and then * checksum extended header and data. */ m->m_pkthdr.len = hdrlen + len; /* in6_cksum() need this */ m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + if (to.to_flags & TOF_SIGNATURE) { + /* + * Calculate MD5 signature and put it into the place + * determined before. + * NOTE: since TCP options buffer doesn't point into + * mbuf's data, calculate offset and use it. + */ + if (!TCPMD5_ENABLED() || TCPMD5_OUTPUT(m, th, + (u_char *)(th + 1) + (to.to_signature - opt)) != 0) { + /* + * Do not send segment if the calculation of MD5 + * digest has failed. + */ + goto out; + } + } +#endif #ifdef INET6 if (isipv6) { /* @@ -1296,7 +1318,7 @@ send: m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen; } -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) KASSERT(len + hdrlen + ipoptlen - ipsec_optlen == m_length(m, NULL), ("%s: mbuf chain shorter than expected: %ld + %u + %u - %u != %u", __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL))); @@ -1553,6 +1575,9 @@ timer: } SOCKBUF_UNLOCK_ASSERT(&so->so_snd); /* Check gotos. */ switch (error) { + case EACCES: + tp->t_softerror = error; + return (0); case EPERM: tp->t_softerror = error; return (error); @@ -1720,7 +1745,6 @@ tcp_addoptions(struct tcpopt *to, u_char *optp) bcopy((u_char *)&to->to_tsecr, optp, sizeof(to->to_tsecr)); optp += sizeof(to->to_tsecr); break; -#ifdef TCP_SIGNATURE case TOF_SIGNATURE: { int siglen = TCPOLEN_SIGNATURE - 2; @@ -1729,8 +1753,10 @@ tcp_addoptions(struct tcpopt *to, u_char *optp) optlen += TCPOLEN_NOP; *optp++ = TCPOPT_NOP; } - if (TCP_MAXOLEN - optlen < TCPOLEN_SIGNATURE) + if (TCP_MAXOLEN - optlen < TCPOLEN_SIGNATURE) { + to->to_flags &= ~TOF_SIGNATURE; continue; + } optlen += TCPOLEN_SIGNATURE; *optp++ = TCPOPT_SIGNATURE; *optp++ = TCPOLEN_SIGNATURE; @@ -1739,7 +1765,6 @@ tcp_addoptions(struct tcpopt *to, u_char *optp) *optp++ = 0; break; } -#endif case TOF_SACK: { int sackblks = 0; diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c index 4b1bfdc..b1c1507 100644 --- a/sys/netinet/tcp_stacks/fastpath.c +++ b/sys/netinet/tcp_stacks/fastpath.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include <sys/param.h> @@ -113,11 +112,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/tcp_offload.h> #endif -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/ipsec6.h> -#endif /*IPSEC*/ - #include <machine/in_cksum.h> #include <security/mac/mac_framework.h> diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 662c435..4fd388b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -114,15 +114,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/tcp_offload.h> #endif -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/xform.h> -#ifdef INET6 -#include <netipsec/ipsec6.h> -#endif -#include <netipsec/key.h> -#include <sys/syslog.h> -#endif /*IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> #include <sys/md5.h> @@ -229,12 +221,6 @@ static int tcp_soreceive_stream; SYSCTL_INT(_net_inet_tcp, OID_AUTO, soreceive_stream, CTLFLAG_RDTUN, &tcp_soreceive_stream, 0, "Using soreceive_stream for TCP sockets"); -#ifdef TCP_SIGNATURE -static int tcp_sig_checksigs = 1; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, signature_verify_input, CTLFLAG_RW, - &tcp_sig_checksigs, 0, "Verify RFC2385 digests on inbound traffic"); -#endif - VNET_DEFINE(uma_zone_t, sack_hole_zone); #define V_sack_hole_zone VNET(sack_hole_zone) @@ -1049,12 +1035,11 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, to.to_tsecr = tp->ts_recent; to.to_flags |= TOF_TS; } -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) /* TCP-MD5 (RFC2385). */ if (tp->t_flags & TF_SIGNATURE) to.to_flags |= TOF_SIGNATURE; #endif - /* Add the options. */ tlen += optlen = tcp_addoptions(&to, optp); @@ -1110,10 +1095,13 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, nth->th_win = htons((u_short)win); nth->th_urp = 0; -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (to.to_flags & TOF_SIGNATURE) { - tcp_signature_compute(m, 0, 0, optlen, to.to_signature, - IPSEC_DIR_OUTBOUND); + if (!TCPMD5_ENABLED() || + TCPMD5_OUTPUT(m, nth, to.to_signature) != 0) { + m_freem(m); + return; + } } #endif @@ -2483,7 +2471,7 @@ tcp_maxseg(const struct tcpcb *tp) optlen = TCPOLEN_TSTAMP_APPA; else optlen = 0; -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (tp->t_flags & TF_SIGNATURE) optlen += PAD(TCPOLEN_SIGNATURE); #endif @@ -2499,7 +2487,7 @@ tcp_maxseg(const struct tcpcb *tp) optlen = PAD(TCPOLEN_MAXSEG); if (tp->t_flags & TF_REQ_SCALE) optlen += PAD(TCPOLEN_WINDOW); -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (tp->t_flags & TF_SIGNATURE) optlen += PAD(TCPOLEN_SIGNATURE); #endif @@ -2511,343 +2499,6 @@ tcp_maxseg(const struct tcpcb *tp) return (tp->t_maxseg - optlen); } -#ifdef IPSEC -/* compute ESP/AH header size for TCP, including outer IP header. */ -size_t -ipsec_hdrsiz_tcp(struct tcpcb *tp) -{ - struct inpcb *inp; - struct mbuf *m; - size_t hdrsiz; - struct ip *ip; -#ifdef INET6 - struct ip6_hdr *ip6; -#endif - struct tcphdr *th; - - if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL) || - (!key_havesp(IPSEC_DIR_OUTBOUND))) - return (0); - m = m_gethdr(M_NOWAIT, MT_DATA); - if (!m) - return (0); - -#ifdef INET6 - if ((inp->inp_vflag & INP_IPV6) != 0) { - ip6 = mtod(m, struct ip6_hdr *); - th = (struct tcphdr *)(ip6 + 1); - m->m_pkthdr.len = m->m_len = - sizeof(struct ip6_hdr) + sizeof(struct tcphdr); - tcpip_fillheaders(inp, ip6, th); - hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); - } else -#endif /* INET6 */ - { - ip = mtod(m, struct ip *); - th = (struct tcphdr *)(ip + 1); - m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr); - tcpip_fillheaders(inp, ip, th); - hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); - } - - m_free(m); - return (hdrsiz); -} -#endif /* IPSEC */ - -#ifdef TCP_SIGNATURE -/* - * Callback function invoked by m_apply() to digest TCP segment data - * contained within an mbuf chain. - */ -static int -tcp_signature_apply(void *fstate, void *data, u_int len) -{ - - MD5Update(fstate, (u_char *)data, len); - return (0); -} - -/* - * XXX The key is retrieved from the system's PF_KEY SADB, by keying a - * search with the destination IP address, and a 'magic SPI' to be - * determined by the application. This is hardcoded elsewhere to 1179 -*/ -struct secasvar * -tcp_get_sav(struct mbuf *m, u_int direction) -{ - union sockaddr_union dst; - struct secasvar *sav; - struct ip *ip; -#ifdef INET6 - struct ip6_hdr *ip6; - char ip6buf[INET6_ADDRSTRLEN]; -#endif - - /* Extract the destination from the IP header in the mbuf. */ - bzero(&dst, sizeof(union sockaddr_union)); - ip = mtod(m, struct ip *); -#ifdef INET6 - ip6 = NULL; /* Make the compiler happy. */ -#endif - switch (ip->ip_v) { -#ifdef INET - case IPVERSION: - dst.sa.sa_len = sizeof(struct sockaddr_in); - dst.sa.sa_family = AF_INET; - dst.sin.sin_addr = (direction == IPSEC_DIR_INBOUND) ? - ip->ip_src : ip->ip_dst; - break; -#endif -#ifdef INET6 - case (IPV6_VERSION >> 4): - ip6 = mtod(m, struct ip6_hdr *); - dst.sa.sa_len = sizeof(struct sockaddr_in6); - dst.sa.sa_family = AF_INET6; - dst.sin6.sin6_addr = (direction == IPSEC_DIR_INBOUND) ? - ip6->ip6_src : ip6->ip6_dst; - break; -#endif - default: - return (NULL); - /* NOTREACHED */ - break; - } - - /* Look up an SADB entry which matches the address of the peer. */ - sav = KEY_ALLOCSA(&dst, IPPROTO_TCP, htonl(TCP_SIG_SPI)); - if (sav == NULL) { - ipseclog((LOG_ERR, "%s: SADB lookup failed for %s\n", __func__, - (ip->ip_v == IPVERSION) ? inet_ntoa(dst.sin.sin_addr) : -#ifdef INET6 - (ip->ip_v == (IPV6_VERSION >> 4)) ? - ip6_sprintf(ip6buf, &dst.sin6.sin6_addr) : -#endif - "(unsupported)")); - } - - return (sav); -} - -/* - * Compute TCP-MD5 hash of a TCP segment. (RFC2385) - * - * Parameters: - * m pointer to head of mbuf chain - * len length of TCP segment data, excluding options - * optlen length of TCP segment options - * buf pointer to storage for computed MD5 digest - * sav pointer to security assosiation - * - * We do this over ip, tcphdr, segment data, and the key in the SADB. - * When called from tcp_input(), we can be sure that th_sum has been - * zeroed out and verified already. - * - * Releases reference to SADB key before return. - * - * Return 0 if successful, otherwise return -1. - * - */ -int -tcp_signature_do_compute(struct mbuf *m, int len, int optlen, - u_char *buf, struct secasvar *sav) -{ -#ifdef INET - struct ippseudo ippseudo; -#endif - MD5_CTX ctx; - int doff; - struct ip *ip; -#ifdef INET - struct ipovly *ipovly; -#endif - struct tcphdr *th; -#ifdef INET6 - struct ip6_hdr *ip6; - struct in6_addr in6; - uint32_t plen; - uint16_t nhdr; -#endif - u_short savecsum; - - KASSERT(m != NULL, ("NULL mbuf chain")); - KASSERT(buf != NULL, ("NULL signature pointer")); - - /* Extract the destination from the IP header in the mbuf. */ - ip = mtod(m, struct ip *); -#ifdef INET6 - ip6 = NULL; /* Make the compiler happy. */ -#endif - - MD5Init(&ctx); - /* - * Step 1: Update MD5 hash with IP(v6) pseudo-header. - * - * XXX The ippseudo header MUST be digested in network byte order, - * or else we'll fail the regression test. Assume all fields we've - * been doing arithmetic on have been in host byte order. - * XXX One cannot depend on ipovly->ih_len here. When called from - * tcp_output(), the underlying ip_len member has not yet been set. - */ - switch (ip->ip_v) { -#ifdef INET - case IPVERSION: - ipovly = (struct ipovly *)ip; - ippseudo.ippseudo_src = ipovly->ih_src; - ippseudo.ippseudo_dst = ipovly->ih_dst; - ippseudo.ippseudo_pad = 0; - ippseudo.ippseudo_p = IPPROTO_TCP; - ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + - optlen); - MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo)); - - th = (struct tcphdr *)((u_char *)ip + sizeof(struct ip)); - doff = sizeof(struct ip) + sizeof(struct tcphdr) + optlen; - break; -#endif -#ifdef INET6 - /* - * RFC 2385, 2.0 Proposal - * For IPv6, the pseudo-header is as described in RFC 2460, namely the - * 128-bit source IPv6 address, 128-bit destination IPv6 address, zero- - * extended next header value (to form 32 bits), and 32-bit segment - * length. - * Note: Upper-Layer Packet Length comes before Next Header. - */ - case (IPV6_VERSION >> 4): - ip6 = mtod(m, struct ip6_hdr *); - in6 = ip6->ip6_src; - in6_clearscope(&in6); - MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr)); - in6 = ip6->ip6_dst; - in6_clearscope(&in6); - MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr)); - plen = htonl(len + sizeof(struct tcphdr) + optlen); - MD5Update(&ctx, (char *)&plen, sizeof(uint32_t)); - nhdr = 0; - MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t)); - MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t)); - MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t)); - nhdr = IPPROTO_TCP; - MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t)); - - th = (struct tcphdr *)((u_char *)ip6 + sizeof(struct ip6_hdr)); - doff = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen; - break; -#endif - default: - KEY_FREESAV(&sav); - return (-1); - /* NOTREACHED */ - break; - } - - - /* - * Step 2: Update MD5 hash with TCP header, excluding options. - * The TCP checksum must be set to zero. - */ - savecsum = th->th_sum; - th->th_sum = 0; - MD5Update(&ctx, (char *)th, sizeof(struct tcphdr)); - th->th_sum = savecsum; - - /* - * Step 3: Update MD5 hash with TCP segment data. - * Use m_apply() to avoid an early m_pullup(). - */ - if (len > 0) - m_apply(m, doff, len, tcp_signature_apply, &ctx); - - /* - * Step 4: Update MD5 hash with shared secret. - */ - MD5Update(&ctx, sav->key_auth->key_data, _KEYLEN(sav->key_auth)); - MD5Final(buf, &ctx); - - key_sa_recordxfer(sav, m); - KEY_FREESAV(&sav); - return (0); -} - -/* - * Compute TCP-MD5 hash of a TCP segment. (RFC2385) - * - * Return 0 if successful, otherwise return -1. - */ -int -tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen, - u_char *buf, u_int direction) -{ - struct secasvar *sav; - - if ((sav = tcp_get_sav(m, direction)) == NULL) - return (-1); - - return (tcp_signature_do_compute(m, len, optlen, buf, sav)); -} - -/* - * Verify the TCP-MD5 hash of a TCP segment. (RFC2385) - * - * Parameters: - * m pointer to head of mbuf chain - * len length of TCP segment data, excluding options - * optlen length of TCP segment options - * buf pointer to storage for computed MD5 digest - * direction direction of flow (IPSEC_DIR_INBOUND or OUTBOUND) - * - * Return 1 if successful, otherwise return 0. - */ -int -tcp_signature_verify(struct mbuf *m, int off0, int tlen, int optlen, - struct tcpopt *to, struct tcphdr *th, u_int tcpbflag) -{ - char tmpdigest[TCP_SIGLEN]; - - if (tcp_sig_checksigs == 0) - return (1); - if ((tcpbflag & TF_SIGNATURE) == 0) { - if ((to->to_flags & TOF_SIGNATURE) != 0) { - - /* - * If this socket is not expecting signature but - * the segment contains signature just fail. - */ - TCPSTAT_INC(tcps_sig_err_sigopt); - TCPSTAT_INC(tcps_sig_rcvbadsig); - return (0); - } - - /* Signature is not expected, and not present in segment. */ - return (1); - } - - /* - * If this socket is expecting signature but the segment does not - * contain any just fail. - */ - if ((to->to_flags & TOF_SIGNATURE) == 0) { - TCPSTAT_INC(tcps_sig_err_nosigopt); - TCPSTAT_INC(tcps_sig_rcvbadsig); - return (0); - } - if (tcp_signature_compute(m, off0, tlen, optlen, &tmpdigest[0], - IPSEC_DIR_INBOUND) == -1) { - TCPSTAT_INC(tcps_sig_err_buildsig); - TCPSTAT_INC(tcps_sig_rcvbadsig); - return (0); - } - - if (bcmp(to->to_signature, &tmpdigest[0], TCP_SIGLEN) != 0) { - TCPSTAT_INC(tcps_sig_rcvbadsig); - return (0); - } - TCPSTAT_INC(tcps_sig_rcvgoodsig); - return (1); -} -#endif /* TCP_SIGNATURE */ - static int sysctl_drop(SYSCTL_HANDLER_ARGS) { diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index ee9bf95..2c24f0e 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -96,13 +96,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/toecore.h> #endif -#ifdef IPSEC -#include <netipsec/ipsec.h> -#ifdef INET6 -#include <netipsec/ipsec6.h> -#endif -#include <netipsec/key.h> -#endif /*IPSEC*/ +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> @@ -736,11 +730,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) INP_HASH_WUNLOCK(&V_tcbinfo); goto abort; } -#ifdef IPSEC - /* Copy old policy into new socket's. */ - if (ipsec_copy_policy(sotoinpcb(lso)->inp_sp, inp->inp_sp)) - printf("syncache_socket: could not copy policy\n"); -#endif #ifdef INET6 if (sc->sc_inc.inc_flags & INC_ISIPV6) { struct inpcb *oinp = sotoinpcb(lso); @@ -822,6 +811,11 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) } } #endif /* INET */ +#if defined(IPSEC) || defined(IPSEC_SUPPORT) + /* Copy old policy into new socket's. */ + if (ipsec_copy_pcbpolicy(sotoinpcb(lso), inp) != 0) + printf("syncache_socket: could not copy policy\n"); +#endif INP_HASH_WUNLOCK(&V_tcbinfo); tp = intotcpcb(inp); tcp_state_change(tp, TCPS_SYN_RECEIVED); @@ -872,7 +866,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) tp->ts_recent_age = tcp_ts_getticks(); tp->ts_offset = sc->sc_tsoff; } -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (sc->sc_flags & SCF_SIGNATURE) tp->t_flags |= TF_SIGNATURE; #endif @@ -996,7 +990,57 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, "(probably spoofed)\n", s, __func__); goto failed; } +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + /* If received ACK has MD5 signature, check it. */ + if ((to->to_flags & TOF_SIGNATURE) != 0 && + (!TCPMD5_ENABLED() || + TCPMD5_INPUT(m, th, to->to_signature) != 0)) { + /* Drop the ACK. */ + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, "%s; %s: Segment rejected, " + "MD5 signature doesn't match.\n", + s, __func__); + free(s, M_TCPLOG); + } + TCPSTAT_INC(tcps_sig_err_sigopt); + return (-1); /* Do not send RST */ + } +#endif /* TCP_SIGNATURE */ } else { +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + /* + * If listening socket requested TCP digests, check that + * received ACK has signature and it is correct. + * If not, drop the ACK and leave sc entry in th cache, + * because SYN was received with correct signature. + */ + if (sc->sc_flags & SCF_SIGNATURE) { + if ((to->to_flags & TOF_SIGNATURE) == 0) { + /* No signature */ + TCPSTAT_INC(tcps_sig_err_nosigopt); + SCH_UNLOCK(sch); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, "%s; %s: Segment " + "rejected, MD5 signature wasn't " + "provided.\n", s, __func__); + free(s, M_TCPLOG); + } + return (-1); /* Do not send RST */ + } + if (!TCPMD5_ENABLED() || + TCPMD5_INPUT(m, th, to->to_signature) != 0) { + /* Doesn't match or no SA */ + SCH_UNLOCK(sch); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, "%s; %s: Segment " + "rejected, MD5 signature doesn't " + "match.\n", s, __func__); + free(s, M_TCPLOG); + } + return (-1); /* Do not send RST */ + } + } +#endif /* TCP_SIGNATURE */ /* * Pull out the entry to unlock the bucket row. * @@ -1262,6 +1306,22 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, ipopts = NULL; #endif +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + /* + * If listening socket requested TCP digests, check that received + * SYN has signature and it is correct. If signature doesn't match + * or TCP_SIGNATURE support isn't enabled, drop the packet. + */ + if (ltflags & TF_SIGNATURE) { + if ((to->to_flags & TOF_SIGNATURE) == 0) { + TCPSTAT_INC(tcps_sig_err_nosigopt); + goto done; + } + if (!TCPMD5_ENABLED() || + TCPMD5_INPUT(m, th, to->to_signature) != 0) + goto done; + } +#endif /* TCP_SIGNATURE */ /* * See if we already have an entry for this connection. * If we do, resend the SYN,ACK, and reset the retransmit timer. @@ -1437,15 +1497,15 @@ skip_alloc: sc->sc_flags |= SCF_WINSCALE; } } -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) /* - * If listening socket requested TCP digests, OR received SYN - * contains the option, flag this in the syncache so that - * syncache_respond() will do the right thing with the SYN+ACK. + * If listening socket requested TCP digests, flag this in the + * syncache so that syncache_respond() will do the right thing + * with the SYN+ACK. */ - if (to->to_flags & TOF_SIGNATURE || ltflags & TF_SIGNATURE) + if (ltflags & TF_SIGNATURE) sc->sc_flags |= SCF_SIGNATURE; -#endif +#endif /* TCP_SIGNATURE */ if (to->to_flags & TOF_SACKPERM) sc->sc_flags |= SCF_SACK; if (to->to_flags & TOF_MSS) @@ -1527,10 +1587,6 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked, #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif -#ifdef TCP_SIGNATURE - struct secasvar *sav; -#endif - hlen = #ifdef INET6 (sc->sc_inc.inc_flags & INC_ISIPV6) ? sizeof(struct ip6_hdr) : @@ -1639,32 +1695,10 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked, } if (sc->sc_flags & SCF_SACK) to.to_flags |= TOF_SACKPERM; -#ifdef TCP_SIGNATURE - sav = NULL; - if (sc->sc_flags & SCF_SIGNATURE) { - sav = tcp_get_sav(m, IPSEC_DIR_OUTBOUND); - if (sav != NULL) - to.to_flags |= TOF_SIGNATURE; - else { - - /* - * We've got SCF_SIGNATURE flag - * inherited from listening socket, - * but no SADB key for given source - * address. Assume signature is not - * required and remove signature flag - * instead of silently dropping - * connection. - */ - if (locked == 0) - SCH_LOCK(sch); - sc->sc_flags &= ~SCF_SIGNATURE; - if (locked == 0) - SCH_UNLOCK(sch); - } - } +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + if (sc->sc_flags & SCF_SIGNATURE) + to.to_flags |= TOF_SIGNATURE; #endif - #ifdef TCP_RFC7413 if (sc->sc_tfo_cookie) { to.to_flags |= TOF_FASTOPEN; @@ -1680,18 +1714,25 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked, th->th_off = (sizeof(struct tcphdr) + optlen) >> 2; m->m_len += optlen; m->m_pkthdr.len += optlen; - -#ifdef TCP_SIGNATURE - if (sc->sc_flags & SCF_SIGNATURE) - tcp_signature_do_compute(m, 0, optlen, - to.to_signature, sav); -#endif #ifdef INET6 if (sc->sc_inc.inc_flags & INC_ISIPV6) ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) + optlen); else #endif ip->ip_len = htons(ntohs(ip->ip_len) + optlen); +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) + if (sc->sc_flags & SCF_SIGNATURE) { + KASSERT(to.to_flags & TOF_SIGNATURE, + ("tcp_addoptions() didn't set tcp_signature")); + + /* NOTE: to.to_signature is inside of mbuf */ + if (!TCPMD5_ENABLED() || + TCPMD5_OUTPUT(m, th, to.to_signature) != 0) { + m_freem(m); + return (EACCES); + } + } +#endif } else optlen = 0; diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index e7187fc..9a53b93 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ipsec.h" #include "opt_tcpdebug.h" #include <sys/param.h> @@ -101,6 +102,7 @@ __FBSDID("$FreeBSD$"); #ifdef TCP_OFFLOAD #include <netinet/tcp_offload.h> #endif +#include <netipsec/ipsec_support.h> /* * TCP protocol interface to socket abstraction. @@ -1533,21 +1535,17 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp switch (sopt->sopt_dir) { case SOPT_SET: switch (sopt->sopt_name) { -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) case TCP_MD5SIG: - INP_WUNLOCK(inp); - error = sooptcopyin(sopt, &optval, sizeof optval, - sizeof optval); + if (!TCPMD5_ENABLED()) { + INP_WUNLOCK(inp); + return (ENOPROTOOPT); + } + error = TCPMD5_PCBCTL(inp, sopt); if (error) return (error); - - INP_WLOCK_RECHECK(inp); - if (optval > 0) - tp->t_flags |= TF_SIGNATURE; - else - tp->t_flags &= ~TF_SIGNATURE; goto unlock_and_done; -#endif /* TCP_SIGNATURE */ +#endif /* IPSEC */ case TCP_NODELAY: case TCP_NOOPT: @@ -1773,11 +1771,13 @@ unlock_and_done: case SOPT_GET: tp = intotcpcb(inp); switch (sopt->sopt_name) { -#ifdef TCP_SIGNATURE +#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) case TCP_MD5SIG: - optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0; - INP_WUNLOCK(inp); - error = sooptcopyout(sopt, &optval, sizeof optval); + if (!TCPMD5_ENABLED()) { + INP_WUNLOCK(inp); + return (ENOPROTOOPT); + } + error = TCPMD5_PCBCTL(inp, sopt); break; #endif diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 7adb717..f65c2fb 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -344,21 +344,6 @@ struct tcpcb { #define TCPOOB_HAVEDATA 0x01 #define TCPOOB_HADDATA 0x02 -#ifdef TCP_SIGNATURE -/* - * Defines which are needed by the xform_tcp module and tcp_[in|out]put - * for SADB verification and lookup. - */ -#define TCP_SIGLEN 16 /* length of computed digest in bytes */ -#define TCP_KEYLEN_MIN 1 /* minimum length of TCP-MD5 key */ -#define TCP_KEYLEN_MAX 80 /* maximum length of TCP-MD5 key */ -/* - * Only a single SA per host may be specified at this time. An SPI is - * needed in order for the KEY_ALLOCSA() lookup to work. - */ -#define TCP_SIG_SPI 0x1000 -#endif /* TCP_SIGNATURE */ - /* * Flags for PLPMTU handling, t_flags2 */ @@ -595,7 +580,7 @@ struct tcpstat { /* TCP_SIGNATURE related stats */ uint64_t tcps_sig_rcvgoodsig; /* Total matching signature received */ uint64_t tcps_sig_rcvbadsig; /* Total bad signature received */ - uint64_t tcps_sig_err_buildsig; /* Mismatching signature received */ + uint64_t tcps_sig_err_buildsig; /* Failed to make signature */ uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */ uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */ @@ -812,17 +797,6 @@ void tcp_tw_zone_change(void); int tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); void tcp_setpersist(struct tcpcb *); -#ifdef TCP_SIGNATURE -struct secasvar; -struct secasvar *tcp_get_sav(struct mbuf *, u_int); -int tcp_signature_do_compute(struct mbuf *, int, int, u_char *, - struct secasvar *); -int tcp_signature_compute(struct mbuf *, int, int, int, u_char *, u_int); -int tcp_signature_verify(struct mbuf *, int, int, int, struct tcpopt *, - struct tcphdr *, u_int); -int tcp_signature_check(struct mbuf *m, int off0, int tlen, int optlen, - struct tcpopt *to, struct tcphdr *th, u_int tcpbflag); -#endif void tcp_slowtimo(void); struct tcptemp * tcpip_maketemplate(struct inpcb *); @@ -866,7 +840,6 @@ tcp_fields_to_host(struct tcphdr *th) th->th_urp = ntohs(th->th_urp); } -#ifdef TCP_SIGNATURE static inline void tcp_fields_to_net(struct tcphdr *th) { @@ -876,7 +849,6 @@ tcp_fields_to_net(struct tcphdr *th) th->th_win = htons(th->th_win); th->th_urp = htons(th->th_urp); } -#endif #endif /* _KERNEL */ #endif /* _NETINET_TCP_VAR_H_ */ diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h index c2d638d..d8475720 100644 --- a/sys/netinet/udp.h +++ b/sys/netinet/udp.h @@ -58,7 +58,7 @@ struct udphdr { */ /* Encapsulation types. */ #define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ -#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-02+ */ +#define UDP_ENCAP_ESPINUDP 2 /* RFC3948 */ /* Default ESP in UDP encapsulation port. */ #define UDP_ENCAP_ESPINUDP_PORT 500 diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 3bf5c6f..c771201 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -92,10 +92,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/udplite.h> #include <netinet/in_rss.h> -#ifdef IPSEC -#include <netipsec/ipsec.h> -#include <netipsec/esp.h> -#endif +#include <netipsec/ipsec_support.h> #include <machine/in_cksum.h> @@ -166,15 +163,6 @@ static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); #endif -#ifdef IPSEC -#ifdef IPSEC_NAT_T -#define UF_ESPINUDP_ALL (UF_ESPINUDP_NON_IKE|UF_ESPINUDP) -#ifdef INET -static struct mbuf *udp4_espdecap(struct inpcb *, struct mbuf *, int); -#endif -#endif /* IPSEC_NAT_T */ -#endif /* IPSEC */ - static void udp_zone_change(void *tag) { @@ -333,21 +321,18 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, off += sizeof(struct udphdr); -#ifdef IPSEC +#if defined(IPSEC) || defined(IPSEC_SUPPORT) /* Check AH/ESP integrity. */ - if (ipsec4_in_reject(n, inp)) { + if (IPSEC_ENABLED(ipv4) && + IPSEC_CHECK_POLICY(ipv4, n, inp) != 0) { m_freem(n); return (0); } -#ifdef IPSEC_NAT_T - up = intoudpcb(inp); - KASSERT(up != NULL, ("%s: udpcb NULL", __func__)); - if (up->u_flags & UF_ESPINUDP_ALL) { /* IPSec UDP encaps. */ - n = udp4_espdecap(inp, n, off); - if (n == NULL) /* Consumed. */ - return (0); + if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */ + if (IPSEC_ENABLED(ipv4) && + UDPENCAP_INPUT(n, off, AF_INET) != 0) + return (0); /* Consumed. */ } -#endif /* IPSEC_NAT_T */ #endif /* IPSEC */ #ifdef MAC if (mac_inpcb_check_deliver(inp, n) != 0) { @@ -1013,42 +998,17 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt) switch (sopt->sopt_dir) { case SOPT_SET: switch (sopt->sopt_name) { +#if defined(IPSEC) || defined(IPSEC_SUPPORT) +#ifdef INET case UDP_ENCAP: - INP_WUNLOCK(inp); - error = sooptcopyin(sopt, &optval, sizeof optval, - sizeof optval); - if (error) - break; - inp = sotoinpcb(so); - KASSERT(inp != NULL, ("%s: inp == NULL", __func__)); - INP_WLOCK(inp); -#ifdef IPSEC_NAT_T - up = intoudpcb(inp); - KASSERT(up != NULL, ("%s: up == NULL", __func__)); -#endif - switch (optval) { - case 0: - /* Clear all UDP encap. */ -#ifdef IPSEC_NAT_T - up->u_flags &= ~UF_ESPINUDP_ALL; -#endif - break; -#ifdef IPSEC_NAT_T - case UDP_ENCAP_ESPINUDP: - case UDP_ENCAP_ESPINUDP_NON_IKE: - up->u_flags &= ~UF_ESPINUDP_ALL; - if (optval == UDP_ENCAP_ESPINUDP) - up->u_flags |= UF_ESPINUDP; - else if (optval == UDP_ENCAP_ESPINUDP_NON_IKE) - up->u_flags |= UF_ESPINUDP_NON_IKE; - break; -#endif - default: - error = EINVAL; - break; + if (!IPSEC_ENABLED(ipv4)) { + INP_WUNLOCK(inp); + return (ENOPROTOOPT); } - INP_WUNLOCK(inp); + error = UDPENCAP_PCBCTL(inp, sopt); break; +#endif /* INET */ +#endif /* IPSEC */ case UDPLITE_SEND_CSCOV: case UDPLITE_RECV_CSCOV: if (!isudplite) { @@ -1085,15 +1045,17 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt) break; case SOPT_GET: switch (sopt->sopt_name) { -#ifdef IPSEC_NAT_T +#if defined(IPSEC) || defined(IPSEC_SUPPORT) +#ifdef INET case UDP_ENCAP: - up = intoudpcb(inp); - KASSERT(up != NULL, ("%s: up == NULL", __func__)); - optval = up->u_flags & UF_ESPINUDP_ALL; - INP_WUNLOCK(inp); - error = sooptcopyout(sopt, &optval, sizeof optval); + if (!IPSEC_ENABLED(ipv4)) { + INP_WUNLOCK(inp); + return (ENOPROTOOPT); + } + error = UDPENCAP_PCBCTL(inp, sopt); break; -#endif +#endif /* INET */ +#endif /* IPSEC */ case UDPLITE_SEND_CSCOV: case UDPLITE_RECV_CSCOV: if (!isudplite) { @@ -1576,142 +1538,6 @@ release: return (error); } - -#if defined(IPSEC) && defined(IPSEC_NAT_T) -/* - * Potentially decap ESP in UDP frame. Check for an ESP header - * and optional marker; if present, strip the UDP header and - * push the result through IPSec. - * - * Returns mbuf to be processed (potentially re-allocated) or - * NULL if consumed and/or processed. - */ -static struct mbuf * -udp4_espdecap(struct inpcb *inp, struct mbuf *m, int off) -{ - size_t minlen, payload, skip, iphlen; - caddr_t data; - struct udpcb *up; - struct m_tag *tag; - struct udphdr *udphdr; - struct ip *ip; - - INP_RLOCK_ASSERT(inp); - - /* - * Pull up data so the longest case is contiguous: - * IP/UDP hdr + non ESP marker + ESP hdr. - */ - minlen = off + sizeof(uint64_t) + sizeof(struct esp); - if (minlen > m->m_pkthdr.len) - minlen = m->m_pkthdr.len; - if ((m = m_pullup(m, minlen)) == NULL) { - IPSECSTAT_INC(ips_in_inval); - return (NULL); /* Bypass caller processing. */ - } - data = mtod(m, caddr_t); /* Points to ip header. */ - payload = m->m_len - off; /* Size of payload. */ - - if (payload == 1 && data[off] == '\xff') - return (m); /* NB: keepalive packet, no decap. */ - - up = intoudpcb(inp); - KASSERT(up != NULL, ("%s: udpcb NULL", __func__)); - KASSERT((up->u_flags & UF_ESPINUDP_ALL) != 0, - ("u_flags 0x%x", up->u_flags)); - - /* - * Check that the payload is large enough to hold an - * ESP header and compute the amount of data to remove. - * - * NB: the caller has already done a pullup for us. - * XXX can we assume alignment and eliminate bcopys? - */ - if (up->u_flags & UF_ESPINUDP_NON_IKE) { - /* - * draft-ietf-ipsec-nat-t-ike-0[01].txt and - * draft-ietf-ipsec-udp-encaps-(00/)01.txt, ignoring - * possible AH mode non-IKE marker+non-ESP marker - * from draft-ietf-ipsec-udp-encaps-00.txt. - */ - uint64_t marker; - - if (payload <= sizeof(uint64_t) + sizeof(struct esp)) - return (m); /* NB: no decap. */ - bcopy(data + off, &marker, sizeof(uint64_t)); - if (marker != 0) /* Non-IKE marker. */ - return (m); /* NB: no decap. */ - skip = sizeof(uint64_t) + sizeof(struct udphdr); - } else { - uint32_t spi; - - if (payload <= sizeof(struct esp)) { - IPSECSTAT_INC(ips_in_inval); - m_freem(m); - return (NULL); /* Discard. */ - } - bcopy(data + off, &spi, sizeof(uint32_t)); - if (spi == 0) /* Non-ESP marker. */ - return (m); /* NB: no decap. */ - skip = sizeof(struct udphdr); - } - - /* - * Setup a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember - * the UDP ports. This is required if we want to select - * the right SPD for multiple hosts behind same NAT. - * - * NB: ports are maintained in network byte order everywhere - * in the NAT-T code. - */ - tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS, - 2 * sizeof(uint16_t), M_NOWAIT); - if (tag == NULL) { - IPSECSTAT_INC(ips_in_nomem); - m_freem(m); - return (NULL); /* Discard. */ - } - iphlen = off - sizeof(struct udphdr); - udphdr = (struct udphdr *)(data + iphlen); - ((uint16_t *)(tag + 1))[0] = udphdr->uh_sport; - ((uint16_t *)(tag + 1))[1] = udphdr->uh_dport; - m_tag_prepend(m, tag); - - /* - * Remove the UDP header (and possibly the non ESP marker) - * IP header length is iphlen - * Before: - * <--- off ---> - * +----+------+-----+ - * | IP | UDP | ESP | - * +----+------+-----+ - * <-skip-> - * After: - * +----+-----+ - * | IP | ESP | - * +----+-----+ - * <-skip-> - */ - ovbcopy(data, data + skip, iphlen); - m_adj(m, skip); - - ip = mtod(m, struct ip *); - ip->ip_len = htons(ntohs(ip->ip_len) - skip); - ip->ip_p = IPPROTO_ESP; - - /* - * We cannot yet update the cksums so clear any - * h/w cksum flags as they are no longer valid. - */ - if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) - m->m_pkthdr.csum_flags &= ~(CSUM_DATA_VALID|CSUM_PSEUDO_HDR); - - (void) ipsec_common_input(m, iphlen, offsetof(struct ip, ip_p), - AF_INET, ip->ip_p); - return (NULL); /* NB: consumed, bypass processing. */ -} -#endif /* defined(IPSEC) && defined(IPSEC_NAT_T) */ - static void udp_abort(struct socket *so) { |