Re: IPsec ours policy check in IPv6 input

2017-05-22 Thread Mike Belopuhov
On 22 May 2017 at 21:02, Alexander Bluhm  wrote:
>
> Hi,
>
> In the IPv4 input path the IPsec policy is checked by
> ip_input_ipsec_ours_check().  This is missing in the IPv6 case.  So
> call this function also from ip6_local().
>
> ok?
>
> bluhm
>

This looks good, but please consider moving these functions out of
ip_input.c :-)


IPsec ours policy check in IPv6 input

2017-05-22 Thread Alexander Bluhm
Hi,

In the IPv4 input path the IPsec policy is checked by
ip_input_ipsec_ours_check().  This is missing in the IPv6 case.  So
call this function also from ip6_local().

ok?

bluhm

Index: netinet/ip_input.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.302
diff -u -p -r1.302 ip_input.c
--- netinet/ip_input.c  16 May 2017 12:24:01 -  1.302
+++ netinet/ip_input.c  22 May 2017 18:42:00 -
@@ -129,9 +129,6 @@ static struct mbuf_queueipsend_mq;
 void   ip_ours(struct mbuf *);
 intip_dooptions(struct mbuf *, struct ifnet *);
 intin_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **);
-#ifdef IPSEC
-intip_input_ipsec_ours_check(struct mbuf *, int);
-#endif /* IPSEC */
 
 static void ip_send_dispatch(void *);
 static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch, 
&ipsend_mq);
@@ -583,7 +580,7 @@ ip_local(struct mbuf *m, int off, int nx
 
 #ifdef IPSEC
if (ipsec_in_use) {
-   if (ip_input_ipsec_ours_check(m, off) != 0) {
+   if (ip_input_ipsec_ours_check(m, off, nxt, AF_INET) != 0) {
ipstat_inc(ips_cantforward);
m_freem(m);
return;
@@ -707,9 +704,8 @@ ip_input_ipsec_fwd_check(struct mbuf *m,
 }
 
 int
-ip_input_ipsec_ours_check(struct mbuf *m, int hlen)
+ip_input_ipsec_ours_check(struct mbuf *m, int hlen, int proto, int af)
 {
-   struct ip *ip = mtod(m, struct ip *);
struct tdb *tdb;
struct tdb_ident *tdbi;
struct m_tag *mtag;
@@ -723,8 +719,8 @@ ip_input_ipsec_ours_check(struct mbuf *m
 * some flexibility in handling nested tunnels (in setting up
 * the policies).
 */
-   if ((ip->ip_p == IPPROTO_ESP) || (ip->ip_p == IPPROTO_AH) ||
-   (ip->ip_p == IPPROTO_IPCOMP))
+   if ((proto == IPPROTO_ESP) || (proto == IPPROTO_AH) ||
+   (proto == IPPROTO_IPCOMP))
return 0;
 
/*
@@ -735,7 +731,16 @@ ip_input_ipsec_ours_check(struct mbuf *m
 * the packet header (the encapsulation routines know how
 * to deal with that).
 */
-   if ((ip->ip_p == IPPROTO_IPIP) || (ip->ip_p == IPPROTO_IPV6))
+   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;
 
/*
@@ -743,7 +748,7 @@ ip_input_ipsec_ours_check(struct mbuf *m
 * policy check in the respective input routine, so we can
 * check for bypass sockets.
 */
-   if ((ip->ip_p == IPPROTO_TCP) || (ip->ip_p == IPPROTO_UDP))
+   if ((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP))
return 0;
 
/*
@@ -764,7 +769,7 @@ ip_input_ipsec_ours_check(struct mbuf *m
tdbi->proto);
} else
tdb = NULL;
-   ipsp_spd_lookup(m, AF_INET, hlen, &error, IPSP_DIRECTION_IN,
+   ipsp_spd_lookup(m, af, hlen, &error, IPSP_DIRECTION_IN,
tdb, NULL, 0);
 
return error;
Index: netinet/ip_var.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.73
diff -u -p -r1.73 ip_var.h
--- netinet/ip_var.h12 May 2017 23:05:58 -  1.73
+++ netinet/ip_var.h22 May 2017 18:02:37 -
@@ -252,6 +252,7 @@ void ipv4_input(struct mbuf *);
 voidip_local(struct mbuf *, int, int);
 voidip_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 *);
 voidrip_init(void);
 int rip_input(struct mbuf **, int *, int, int);
Index: netinet6/ip6_input.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.186
diff -u -p -r1.186 ip6_input.c
--- netinet6/ip6_input.c12 May 2017 14:04:09 -  1.186
+++ netinet6/ip6_input.c22 May 2017 17:47:06 -
@@ -550,6 +550,18 @@ ip6_local(struct mbuf *m, int off, int n
goto bad;
}
 
+#ifdef IPSEC
+   if (ipsec_in_use) {
+   if (ip_input_ipsec_ours_check(m, off, nxt, AF_INET6)
+   != 0) {
+   ipstat_inc(ip6s_cantforward);
+   m_freem(m);
+   return;
+