diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-05-22 22:23:12 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-05-22 22:23:12 +0000 |
commit | b376c2299161706e6d307dbc5f27b7112fdf0ed4 (patch) | |
tree | f3a2a7441124ad8340fb6627011cf2fd75dd7fbb /sys/netinet | |
parent | a8acecaa47b45308f1a5eb46637f58e6fcf6562f (diff) |
Move IPsec forward and local policy check functions to ipsec_input.c
and give them better names.
input and OK mikeb@
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 103 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 4 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 4 | ||||
-rw-r--r-- | sys/netinet/ipsec_input.c | 97 |
4 files changed, 103 insertions, 105 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 194a51ff19b..f378cf3f174 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.303 2017/05/22 20:04:12 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.304 2017/05/22 22:23:11 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -442,7 +442,7 @@ ipv4_input(struct mbuf *m) int rv; KERNEL_LOCK(); - rv = ip_input_ipsec_fwd_check(m, hlen, AF_INET); + rv = ipsec_forward_check(m, hlen, AF_INET); KERNEL_UNLOCK(); if (rv != 0) { ipstat_inc(ips_cantforward); @@ -580,7 +580,7 @@ ip_local(struct mbuf *m, int off, int nxt) #ifdef IPSEC if (ipsec_in_use) { - if (ip_input_ipsec_ours_check(m, off, nxt, AF_INET) != 0) { + if (ipsec_local_check(m, off, nxt, AF_INET) != 0) { ipstat_inc(ips_cantforward); m_freem(m); return; @@ -679,103 +679,6 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt) return (match); } -#ifdef IPSEC -int -ip_input_ipsec_fwd_check(struct mbuf *m, int hlen, int af) -{ - struct tdb *tdb; - struct tdb_ident *tdbi; - struct m_tag *mtag; - int error = 0; - - /* - * IPsec policy check for forwarded packets. Look at - * inner-most IPsec SA used. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); - } else - tdb = NULL; - ipsp_spd_lookup(m, af, hlen, &error, IPSP_DIRECTION_IN, tdb, NULL, 0); - - return error; -} - -int -ip_input_ipsec_ours_check(struct mbuf *m, int hlen, int proto, int af) -{ - struct tdb *tdb; - struct tdb_ident *tdbi; - struct m_tag *mtag; - int error = 0; - - /* - * If it's a protected packet for us, skip the policy check. - * That's because we really only care about the properties of - * the protected packet, and not the intermediate versions. - * While this is not the most paranoid setting, it allows - * some flexibility in handling nested tunnels (in setting up - * the policies). - */ - if ((proto == IPPROTO_ESP) || (proto == IPPROTO_AH) || - (proto == IPPROTO_IPCOMP)) - return 0; - - /* - * If the protected packet was tunneled, then we need to - * verify the protected packet's information, not the - * external headers. Thus, skip the policy lookup for the - * external packet, and keep the IPsec information linked on - * the packet header (the encapsulation routines know how - * to deal with that). - */ - if ((proto == IPPROTO_IPV4) || (proto == IPPROTO_IPV6)) - return 0; - - /* - * When processing IPv6 header chains, do not look at the - * outer header. The inner protocol is relevant and will - * be checked by the local delivery loop later. - */ - if ((af == AF_INET6) && ((proto == IPPROTO_DSTOPTS) || - (proto == IPPROTO_ROUTING) || (proto == IPPROTO_FRAGMENT))) - return 0; - - /* - * If the protected packet is TCP or UDP, we'll do the - * policy check in the respective input routine, so we can - * check for bypass sockets. - */ - if ((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) - return 0; - - /* - * IPsec policy check for local-delivery packets. Look at the - * inner-most SA that protected the packet. This is in fact - * a bit too restrictive (it could end up causing packets to - * be dropped that semantically follow the policy, e.g., in - * certain SA-bundle configurations); but the alternative is - * very complicated (and requires keeping track of what - * kinds of tunneling headers have been seen in-between the - * IPsec headers), and I don't think we lose much functionality - * that's needed in the real world (who uses bundles anyway ?). - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag) { - tdbi = (struct tdb_ident *)(mtag + 1); - tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, - tdbi->proto); - } else - tdb = NULL; - ipsp_spd_lookup(m, af, hlen, &error, IPSP_DIRECTION_IN, - tdb, NULL, 0); - - return error; -} -#endif /* IPSEC */ - /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index 44496a53bf4..43bf0f8b66a 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.181 2017/05/18 10:56:45 bluhm Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.182 2017/05/22 22:23:11 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -552,6 +552,8 @@ int ipsec_delete_policy(struct ipsec_policy *); ssize_t ipsec_hdrsz(struct tdb *); void ipsec_adjust_mtu(struct mbuf *, u_int32_t); struct ipsec_acquire *ipsec_get_acquire(u_int32_t); +int ipsec_forward_check(struct mbuf *, int, int); +int ipsec_local_check(struct mbuf *, int, int, int); #endif /* _KERNEL */ #endif /* _NETINET_IPSP_H_ */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 0bd1152bcde..9653c1de27b 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.74 2017/05/22 20:04:12 bluhm Exp $ */ +/* $OpenBSD: ip_var.h,v 1.75 2017/05/22 22:23:11 bluhm Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -251,8 +251,6 @@ void ipintr(void); void ipv4_input(struct mbuf *); void ip_local(struct mbuf *, int, int); void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int); -int ip_input_ipsec_fwd_check(struct mbuf *, int, int); -int ip_input_ipsec_ours_check(struct mbuf *, int, int, int); int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); void rip_init(void); int rip_input(struct mbuf **, int *, int, int); diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c index 08efc2d4c60..8c981aa722a 100644 --- a/sys/netinet/ipsec_input.c +++ b/sys/netinet/ipsec_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec_input.c,v 1.152 2017/05/16 12:24:02 mpi Exp $ */ +/* $OpenBSD: ipsec_input.c,v 1.153 2017/05/22 22:23:11 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -1013,3 +1013,98 @@ ipcomp6_input(struct mbuf **mp, int *offp, int proto, int af) return IPPROTO_DONE; } #endif /* INET6 */ + +int +ipsec_forward_check(struct mbuf *m, int hlen, int af) +{ + struct tdb *tdb; + struct tdb_ident *tdbi; + struct m_tag *mtag; + int error = 0; + + /* + * IPsec policy check for forwarded packets. Look at + * inner-most IPsec SA used. + */ + mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); + if (mtag != NULL) { + tdbi = (struct tdb_ident *)(mtag + 1); + tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, tdbi->proto); + } else + tdb = NULL; + ipsp_spd_lookup(m, af, hlen, &error, IPSP_DIRECTION_IN, tdb, NULL, 0); + + return error; +} + +int +ipsec_local_check(struct mbuf *m, int hlen, int proto, int af) +{ + struct tdb *tdb; + struct tdb_ident *tdbi; + struct m_tag *mtag; + int error = 0; + + /* + * If it's a protected packet for us, skip the policy check. + * That's because we really only care about the properties of + * the protected packet, and not the intermediate versions. + * While this is not the most paranoid setting, it allows + * some flexibility in handling nested tunnels (in setting up + * the policies). + */ + if ((proto == IPPROTO_ESP) || (proto == IPPROTO_AH) || + (proto == IPPROTO_IPCOMP)) + return 0; + + /* + * If the protected packet was tunneled, then we need to + * verify the protected packet's information, not the + * external headers. Thus, skip the policy lookup for the + * external packet, and keep the IPsec information linked on + * the packet header (the encapsulation routines know how + * to deal with that). + */ + if ((proto == IPPROTO_IPV4) || (proto == IPPROTO_IPV6)) + return 0; + + /* + * When processing IPv6 header chains, do not look at the + * outer header. The inner protocol is relevant and will + * be checked by the local delivery loop later. + */ + if ((af == AF_INET6) && ((proto == IPPROTO_DSTOPTS) || + (proto == IPPROTO_ROUTING) || (proto == IPPROTO_FRAGMENT))) + return 0; + + /* + * If the protected packet is TCP or UDP, we'll do the + * policy check in the respective input routine, so we can + * check for bypass sockets. + */ + if ((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) + return 0; + + /* + * IPsec policy check for local-delivery packets. Look at the + * inner-most SA that protected the packet. This is in fact + * a bit too restrictive (it could end up causing packets to + * be dropped that semantically follow the policy, e.g., in + * certain SA-bundle configurations); but the alternative is + * very complicated (and requires keeping track of what + * kinds of tunneling headers have been seen in-between the + * IPsec headers), and I don't think we lose much functionality + * that's needed in the real world (who uses bundles anyway ?). + */ + mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); + if (mtag) { + tdbi = (struct tdb_ident *)(mtag + 1); + tdb = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, + tdbi->proto); + } else + tdb = NULL; + ipsp_spd_lookup(m, af, hlen, &error, IPSP_DIRECTION_IN, + tdb, NULL, 0); + + return error; +} |