Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys PR/47886: Dr. Wolfgang Stukenbrock: IPSEC_NAT_T enabled ...



details:   https://anonhg.NetBSD.org/src/rev/2030ec6d3465
branches:  trunk
changeset: 787161:2030ec6d3465
user:      christos <christos%NetBSD.org@localhost>
date:      Tue Jun 04 22:47:37 2013 +0000

description:
PR/47886: Dr. Wolfgang Stukenbrock: IPSEC_NAT_T enabled kernels may access
outdated pointers and pass ESP data to UPD-sockets.
While here, simplify the code and remove the IPSEC_NAT_T option; always
compile nat-traversal in so that it does not bitrot.

diffstat:

 sys/netinet/ip_output.c     |  36 +++++++++++------------------
 sys/netinet/udp_usrreq.c    |  47 ++++++++++++++++++---------------------
 sys/netipsec/files.netipsec |   3 +-
 sys/netipsec/ipsec.c        |  15 +++++++++++-
 sys/netipsec/ipsec.h        |   4 ++-
 sys/netipsec/ipsec_input.c  |  18 ++++-----------
 sys/netipsec/ipsec_output.c |  14 +----------
 sys/netipsec/key.c          |  53 ++------------------------------------------
 sys/netipsec/key.h          |   4 +--
 sys/netipsec/keydb.h        |   4 +--
 sys/netipsec/xform_ah.c     |  18 ++++-----------
 sys/netipsec/xform_esp.c    |  18 ++++-----------
 sys/netipsec/xform_ipcomp.c |  18 ++++-----------
 13 files changed, 80 insertions(+), 172 deletions(-)

diffs (truncated from 931 to 300 lines):

diff -r 77fa6a423f36 -r 2030ec6d3465 sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Tue Jun 04 22:45:07 2013 +0000
+++ b/sys/netinet/ip_output.c   Tue Jun 04 22:47:37 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_output.c,v 1.218 2013/02/02 07:00:40 kefren Exp $   */
+/*     $NetBSD: ip_output.c,v 1.219 2013/06/04 22:47:37 christos Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.218 2013/02/02 07:00:40 kefren Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.219 2013/06/04 22:47:37 christos Exp $");
 
 #include "opt_pfil_hooks.h"
 #include "opt_inet.h"
@@ -126,6 +126,7 @@
 #include <netinet/ip_private.h>
 #include <netinet/in_offload.h>
 #include <netinet/portalgo.h>
+#include <netinet/udp.h>
 
 #ifdef MROUTING
 #include <netinet/ip_mroute.h>
@@ -137,9 +138,6 @@
 #include <netipsec/xform.h>
 #endif /* FAST_IPSEC*/
 
-#ifdef IPSEC_NAT_T
-#include <netinet/udp.h>
-#endif
 
 static struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *);
 static struct ifnet *ip_multicast_if(struct in_addr *, int *);
@@ -179,9 +177,7 @@
        struct ip_moptions *imo;
        struct socket *so;
        va_list ap;
-#ifdef IPSEC_NAT_T
        int natt_frag = 0;
-#endif
 #ifdef FAST_IPSEC
        struct inpcb *inp;
        struct secpolicy *sp = NULL;
@@ -518,22 +514,20 @@
                 *    sp == NULL, error != 0        discard packet, report error
                 */
                if (sp != NULL) {
-#ifdef IPSEC_NAT_T
                        /*
-                        * NAT-T ESP fragmentation: don't do IPSec processing now,
-                        * we'll do it on each fragmented packet.
+                        * NAT-T ESP fragmentation: don't do IPSec processing
+                        * now, we'll do it on each fragmented packet.
                         */
-                       if (sp->req->sav &&
-                                       ((sp->req->sav->natt_type & UDP_ENCAP_ESPINUDP) ||
-                                        (sp->req->sav->natt_type & UDP_ENCAP_ESPINUDP_NON_IKE))) {
-                               if (ntohs(ip->ip_len) > sp->req->sav->esp_frag) {
+                       if (sp->req->sav && (sp->req->sav->natt_type &
+                           (UDP_ENCAP_ESPINUDP|UDP_ENCAP_ESPINUDP_NON_IKE))) {
+                               if (ntohs(ip->ip_len) > sp->req->sav->esp_frag)
+                               {
                                        natt_frag = 1;
                                        mtu = sp->req->sav->esp_frag;
                                        splx(s);
                                        goto spd_done;
                                }
                        }
-#endif /* IPSEC_NAT_T */
 
                        /*
                         * Do delayed checksums now because we send before
@@ -711,19 +705,17 @@
                                ia->ia_ifa.ifa_data.ifad_outbytes +=
                                    ntohs(ip->ip_len);
 #endif
-#ifdef IPSEC_NAT_T
                        /*
-                        * If we get there, the packet has not been handeld by
+                        * If we get there, the packet has not been handled by
                         * IPSec whereas it should have. Now that it has been
                         * fragmented, re-inject it in ip_output so that IPsec
                         * processing can occur.
                         */
                        if (natt_frag) {
-                               error = ip_output(m, opt,
-                                   ro, flags | IP_RAWOUTPUT | IP_NOIPNEWID, imo, so, mtu_p);
-                       } else
-#endif /* IPSEC_NAT_T */
-                       {
+                               error = ip_output(m, opt, ro,
+                                   flags | IP_RAWOUTPUT | IP_NOIPNEWID,
+                                   imo, so, mtu_p);
+                       } else {
                                KASSERT((m->m_pkthdr.csum_flags &
                                    (M_CSUM_UDPv4 | M_CSUM_TCPv4)) == 0);
                                KERNEL_LOCK(1, NULL);
diff -r 77fa6a423f36 -r 2030ec6d3465 sys/netinet/udp_usrreq.c
--- a/sys/netinet/udp_usrreq.c  Tue Jun 04 22:45:07 2013 +0000
+++ b/sys/netinet/udp_usrreq.c  Tue Jun 04 22:47:37 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: udp_usrreq.c,v 1.187 2012/06/22 14:54:35 christos Exp $        */
+/*     $NetBSD: udp_usrreq.c,v 1.188 2013/06/04 22:47:37 christos Exp $        */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.187 2012/06/22 14:54:35 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.188 2013/06/04 22:47:37 christos Exp $");
 
 #include "opt_inet.h"
 #include "opt_compat_netbsd.h"
@@ -148,10 +148,8 @@
 percpu_t *udpstat_percpu;
 
 #ifdef INET
-#ifdef IPSEC_NAT_T
 static int udp4_espinudp (struct mbuf **, int, struct sockaddr *,
        struct socket *);
-#endif
 static void udp4_sendup (struct mbuf *, int, struct sockaddr *,
        struct socket *);
 static int udp4_realinput (struct sockaddr_in *, struct sockaddr_in *,
@@ -404,6 +402,14 @@
                UDP_STATINC(UDP_STAT_HDROPS);
                return;
        }
+       if (m == NULL) {
+               /*
+                * packet has been processed by ESP stuff -
+                * e.g. dropped NAT-T-keep-alive-packet ...
+                */
+               return;
+       }
+       ip = mtod(m, struct ip *);
 #ifdef INET6
        if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
                struct sockaddr_in6 src6, dst6;
@@ -804,7 +810,6 @@
                                return rcvcnt;
                }
 
-#ifdef IPSEC_NAT_T
                /* Handle ESP over UDP */
                if (inp->inp_flags & INP_ESPINUDP_ALL) {
                        struct sockaddr *sa = (struct sockaddr *)src;
@@ -830,7 +835,6 @@
                                break;
                        }
                }
-#endif
 
                /*
                 * Check the minimum TTL for socket.
@@ -1058,7 +1062,6 @@
                                break;
 
                        switch(optval) {
-#ifdef IPSEC_NAT_T
                        case 0:
                                inp->inp_flags &= ~INP_ESPINUDP_ALL;
                                break;
@@ -1072,7 +1075,6 @@
                                inp->inp_flags &= ~INP_ESPINUDP_ALL;
                                inp->inp_flags |= INP_ESPINUDP_NON_IKE;
                                break;
-#endif
                        default:
                                error = EINVAL;
                                break;
@@ -1437,7 +1439,7 @@
        UDP_STATINC(stat);
 }
 
-#if (defined INET && defined IPSEC_NAT_T)
+#if defined(INET)
 /*
  * Returns:
  * 1 if the packet was processed
@@ -1455,7 +1457,6 @@
        size_t minlen;
        size_t iphdrlen;
        struct ip *ip;
-       struct mbuf *n;
        struct m_tag *tag;
        struct udphdr *udphdr;
        u_int16_t sport, dport;
@@ -1483,6 +1484,8 @@
 
        /* Ignore keepalive packets */
        if ((len == 1) && (*(unsigned char *)data == 0xff)) {
+               m_free(m);
+               *mp = NULL; /* avoid any further processiong by caller ... */
                return 1;
        }
 
@@ -1542,16 +1545,9 @@
        ip->ip_p = IPPROTO_ESP;
 
        /*
-        * Copy the mbuf to avoid multiple free, as both
-        * esp4_input (which we call) and udp_input (which
-        * called us) free the mbuf.
-        */
-       if ((n = m_dup(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
-               printf("udp4_espinudp: m_dup failed\n");
-               return 0;
-       }
-
-       /*
+        * We have modified the packet - it is now ESP, so we should not
+        * return to UDP processing ... 
+        *
         * Add a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember
         * the source UDP port. This is required if we want
         * to select the right SPD for multiple hosts behind 
@@ -1560,20 +1556,21 @@
        if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
            sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {
                printf("udp4_espinudp: m_tag_get failed\n");
-               m_freem(n);
-               return 0;
+               m_freem(m);
+               return -1;
        }
        ((u_int16_t *)(tag + 1))[0] = sport;
        ((u_int16_t *)(tag + 1))[1] = dport;
-       m_tag_prepend(n, tag);
+       m_tag_prepend(m, tag);
 
 #ifdef FAST_IPSEC
-       ipsec4_common_input(n, iphdrlen, IPPROTO_ESP);
+       ipsec4_common_input(m, iphdrlen, IPPROTO_ESP);
 #else
-       esp4_input(n, iphdrlen);
+       esp4_input(m, iphdrlen);
 #endif
 
        /* We handled it, it shouldn't be handled by UDP */
+       *mp = NULL; /* avoid free by caller ... */
        return 1;
 }
 #endif
diff -r 77fa6a423f36 -r 2030ec6d3465 sys/netipsec/files.netipsec
--- a/sys/netipsec/files.netipsec       Tue Jun 04 22:45:07 2013 +0000
+++ b/sys/netipsec/files.netipsec       Tue Jun 04 22:47:37 2013 +0000
@@ -1,9 +1,8 @@
-#      $Id: files.netipsec,v 1.10 2012/03/22 20:34:42 drochner Exp $
+#      $Id: files.netipsec,v 1.11 2013/06/04 22:47:37 christos Exp $
 #
 #
 defflag opt_ipsec.h    FAST_IPSEC:     opencrypto
 defflag opt_ipsec.h    IPSEC: FAST_IPSEC
-defflag opt_ipsec.h    IPSEC_NAT_T
 defflag opt_ipsec.h    IPSEC_DEBUG
 
 file   netipsec/ipsec.c                fast_ipsec      needs-flag
diff -r 77fa6a423f36 -r 2030ec6d3465 sys/netipsec/ipsec.c
--- a/sys/netipsec/ipsec.c      Tue Jun 04 22:45:07 2013 +0000
+++ b/sys/netipsec/ipsec.c      Tue Jun 04 22:47:37 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsec.c,v 1.57 2012/12/07 15:29:38 christos Exp $      */
+/*     $NetBSD: ipsec.c,v 1.58 2013/06/04 22:47:37 christos Exp $      */
 /*     $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $       */
 /*     $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.57 2012/12/07 15:29:38 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.58 2013/06/04 22:47:37 christos Exp $");
 
 /*
  * IPsec controller part.
@@ -2274,6 +2274,17 @@
        return EINVAL;
 }
 
+void
+nat_t_ports_get(struct mbuf *m, u_int16_t *dport, u_int16_t *sport) {
+       struct m_tag *tag;
+
+       if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) {
+               *sport = ((u_int16_t *)(tag + 1))[0];
+               *dport = ((u_int16_t *)(tag + 1))[1];
+       } else
+               *sport = *dport = 0;
+}
+
 #ifdef __NetBSD__
 /*
  * XXXJRT This should be done as a protosw init call.
diff -r 77fa6a423f36 -r 2030ec6d3465 sys/netipsec/ipsec.h



Home | Main Index | Thread Index | Old Index