Source-Changes-HG archive

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

[src/trunk]: src/sys fix two bugs in the PFKEY interface:



details:   https://anonhg.NetBSD.org/src/rev/733623e75fb4
branches:  trunk
changeset: 757556:733623e75fb4
user:      spz <spz%NetBSD.org@localhost>
date:      Sun Sep 05 06:52:53 2010 +0000

description:
fix two bugs in the PFKEY interface:

1) RFC2367 says in 2.3.3 Address Extension: "All non-address
   information in the sockaddrs, such as sin_zero for AF_INET sockaddrs,
   and sin6_flowinfo for AF_INET6 sockaddrs, MUST be zeroed out."
   the IPSEC_NAT_T code was expecting the port information it needs
   to be conveyed in the sockaddr instead of exclusively by
   SADB_X_EXT_NAT_T_SPORT and SADB_X_EXT_NAT_T_DPORT,
   and was not zeroing out the port information in the non-nat-traversal
   case.
   Since it was expecting the port information to reside in the sockaddr
   it could get away with (re)setting the ports after starting to use them.
   -> Set the natt ports before setting the SA mature.

2) RFC3947 has two Original Address fields, initiator and responder,
   so we need SADB_X_EXT_NAT_T_OAI and SADB_X_EXT_NAT_T_OAR and not just
   SADB_X_EXT_NAT_T_OA

The change has been created using vanhu's patch for FreeBSD as reference.

Note that establishing actual nat-t sessions has not yet been tested.

Likely fixes the following:
PR bin/41757
PR net/42592
PR net/42606

diffstat:

 sys/net/pfkeyv2.h  |   10 +-
 sys/netipsec/key.c |  178 +++++++++++++++++++++----
 sys/netkey/key.c   |  357 ++++++++++++++++++++++++++++++----------------------
 3 files changed, 361 insertions(+), 184 deletions(-)

diffs (truncated from 922 to 300 lines):

diff -r a362825e1ff7 -r 733623e75fb4 sys/net/pfkeyv2.h
--- a/sys/net/pfkeyv2.h Sun Sep 05 06:49:13 2010 +0000
+++ b/sys/net/pfkeyv2.h Sun Sep 05 06:52:53 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pfkeyv2.h,v 1.26 2008/02/20 17:05:53 matt Exp $        */
+/*     $NetBSD: pfkeyv2.h,v 1.27 2010/09/05 06:52:53 spz Exp $ */
 /*     $KAME: pfkeyv2.h,v 1.36 2003/07/25 09:33:37 itojun Exp $        */
 
 /*
@@ -310,14 +310,16 @@
 #define SADB_X_EXT_NAT_T_TYPE         20
 #define SADB_X_EXT_NAT_T_SPORT        21
 #define SADB_X_EXT_NAT_T_DPORT        22
-#define SADB_X_EXT_NAT_T_OA           23
-#define SADB_X_EXT_NAT_T_FRAG        24
+#define SADB_X_EXT_NAT_T_OA           23       /* compat */
+#define SADB_X_EXT_NAT_T_OAI          23
+#define SADB_X_EXT_NAT_T_OAR          24
+#define SADB_X_EXT_NAT_T_FRAG        25
 #if 0
 #define        SADB_X_EXT_TAG                25        /* KAME */
 #define        SADB_X_EXT_SA3                26        /* KAME */
 #define        SADB_X_EXT_PACKET             27        /* KAME */
 #endif
-#define SADB_EXT_MAX                  24
+#define SADB_EXT_MAX                  25
 
 #define SADB_SATYPE_UNSPEC     0
 #define SADB_SATYPE_AH         2
diff -r a362825e1ff7 -r 733623e75fb4 sys/netipsec/key.c
--- a/sys/netipsec/key.c        Sun Sep 05 06:49:13 2010 +0000
+++ b/sys/netipsec/key.c        Sun Sep 05 06:52:53 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.63 2010/01/31 00:43:38 hubertf Exp $ */
+/*     $NetBSD: key.c,v 1.64 2010/09/05 06:52:53 spz Exp $     */
 /*     $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $        */
 /*     $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */
        
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.63 2010/01/31 00:43:38 hubertf Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.64 2010/09/05 06:52:53 spz Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -192,7 +192,8 @@
        sizeof(struct sadb_x_nat_t_type),       /* SADB_X_EXT_NAT_T_TYPE */
        sizeof(struct sadb_x_nat_t_port),       /* SADB_X_EXT_NAT_T_SPORT */
        sizeof(struct sadb_x_nat_t_port),       /* SADB_X_EXT_NAT_T_DPORT */
-       sizeof(struct sadb_address),            /* SADB_X_EXT_NAT_T_OA */
+       sizeof(struct sadb_address),            /* SADB_X_EXT_NAT_T_OAI */
+       sizeof(struct sadb_address),            /* SADB_X_EXT_NAT_T_OAR */
        sizeof(struct sadb_x_nat_t_frag),       /* SADB_X_EXT_NAT_T_FRAG */
 };
 static const int maxsize[] = {
@@ -219,7 +220,8 @@
        sizeof(struct sadb_x_nat_t_type),       /* SADB_X_EXT_NAT_T_TYPE */
        sizeof(struct sadb_x_nat_t_port),       /* SADB_X_EXT_NAT_T_SPORT */
        sizeof(struct sadb_x_nat_t_port),       /* SADB_X_EXT_NAT_T_DPORT */
-       0,                                      /* SADB_X_EXT_NAT_T_OA */
+       0,                                      /* SADB_X_EXT_NAT_T_OAI */
+       0,                                      /* SADB_X_EXT_NAT_T_OAR */
        sizeof(struct sadb_x_nat_t_frag),       /* SADB_X_EXT_NAT_T_FRAG */
 };
 
@@ -465,6 +467,9 @@
 #ifdef IPSEC_NAT_T
 static int key_handle_natt_info (struct secasvar *, 
                                     const struct sadb_msghdr *);
+static int key_set_natt_ports (union sockaddr_union *,
+                               union sockaddr_union *,
+                               const struct sadb_msghdr *);
 #endif
 static int key_update (struct socket *, struct mbuf *,
        const struct sadb_msghdr *);
@@ -2574,7 +2579,7 @@
        struct sadb_x_nat_t_type *type;
        struct sadb_x_nat_t_port *sport;
        struct sadb_x_nat_t_port *dport;
-       struct sadb_address *addr;
+       struct sadb_address *iaddr, *raddr;
        struct sadb_x_nat_t_frag *frag;
 
        /* sanity check */
@@ -2594,8 +2599,14 @@
                return key_senderror(so, m, EINVAL);
        }
 
-       if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) &&
-               (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+       if ((mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) &&
+               (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+               ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
+               return key_senderror(so, m, EINVAL);
+       }
+
+       if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+               (mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
                ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
                return key_senderror(so, m, EINVAL);
        }
@@ -2609,7 +2620,8 @@
        type = (struct sadb_x_nat_t_type *)mhp->ext[SADB_X_EXT_NAT_T_TYPE];
        sport = (struct sadb_x_nat_t_port *)mhp->ext[SADB_X_EXT_NAT_T_SPORT];
        dport = (struct sadb_x_nat_t_port *)mhp->ext[SADB_X_EXT_NAT_T_DPORT];
-       addr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OA];
+       iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI];
+       raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR];
        frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG];
 
        printf("sadb_nat_map called\n");
@@ -3522,8 +3534,9 @@
                SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC,
                SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY,
 #ifdef IPSEC_NAT_T
-               SADB_X_EXT_NAT_T_TYPE, SADB_X_EXT_NAT_T_SPORT,
-               SADB_X_EXT_NAT_T_DPORT, SADB_X_EXT_NAT_T_OA,
+               SADB_X_EXT_NAT_T_TYPE,
+               SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT,
+               SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR,
                SADB_X_EXT_NAT_T_FRAG,
 #endif
 
@@ -3623,7 +3636,8 @@
                                goto fail;
                        break;
 
-               case SADB_X_EXT_NAT_T_OA:
+               case SADB_X_EXT_NAT_T_OAI:
+               case SADB_X_EXT_NAT_T_OAR:
                case SADB_X_EXT_NAT_T_FRAG:
                        continue;
 #endif
@@ -4212,9 +4226,20 @@
         * If NAT-T is enabled, check ports for tunnel mode.
         * Don't do it for transport mode, as there is no
         * port information available in the SP.
+         * Also don't check ports if they are set to zero
+        * in the SPD: This means we have a non-generated
+        * SPD which can't know UDP ports.
         */
 #ifdef IPSEC_NAT_T
-       if (saidx1->mode == IPSEC_MODE_TUNNEL)
+       if (saidx1->mode == IPSEC_MODE_TUNNEL &&
+           ((((const struct sockaddr *)(&saidx1->src))->sa_family == AF_INET &&
+             ((const struct sockaddr *)(&saidx1->dst))->sa_family == AF_INET &&
+             ((const struct sockaddr_in *)(&saidx1->src))->sin_port &&
+             ((const struct sockaddr_in *)(&saidx1->dst))->sin_port) ||
+             (((const struct sockaddr *)(&saidx1->src))->sa_family == AF_INET6 &&
+             ((const struct sockaddr *)(&saidx1->dst))->sa_family == AF_INET6 &&
+             ((const struct sockaddr_in6 *)(&saidx1->src))->sin6_port &&
+             ((const struct sockaddr_in6 *)(&saidx1->dst))->sin6_port)))
                chkport = 1;
 #endif
 
@@ -4908,6 +4933,11 @@
                                     dst0 + 1, &saidx)) != 0)
                return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+       if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+               return key_senderror(so, m, EINVAL);
+#endif
+
        /* SPI allocation */
        spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
                               &saidx);
@@ -5092,8 +5122,10 @@
                     const struct sadb_msghdr *mhp)
 {
 
-       if (mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL)
-               printf("update: NAT-T OA present\n");
+       if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
+               ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+       if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
+               ipseclog((LOG_DEBUG,"update: NAT-T OAr present\n"));
 
        if ((mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL) &&
            (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL) &&
@@ -5101,7 +5133,7 @@
                struct sadb_x_nat_t_type *type;
                struct sadb_x_nat_t_port *sport;
                struct sadb_x_nat_t_port *dport;
-               struct sadb_address *addr;
+               struct sadb_address *iaddr, *raddr;
                struct sadb_x_nat_t_frag *frag;
 
                if ((mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type)) ||
@@ -5112,8 +5144,14 @@
                        return -1;
                }
 
-               if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) &&
-                   (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+               if ((mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) &&
+                   (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+                       ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
+                       return -1;
+               }
+
+               if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+                   (mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
                        ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
                        return -1;
                }
@@ -5130,11 +5168,19 @@
                    mhp->ext[SADB_X_EXT_NAT_T_SPORT];
                dport = (struct sadb_x_nat_t_port *)
                    mhp->ext[SADB_X_EXT_NAT_T_DPORT];
-               addr = (struct sadb_address *)
-                   mhp->ext[SADB_X_EXT_NAT_T_OA];
+               iaddr = (struct sadb_address *)
+                   mhp->ext[SADB_X_EXT_NAT_T_OAI];
+               raddr = (struct sadb_address *)
+                   mhp->ext[SADB_X_EXT_NAT_T_OAR];
                frag = (struct sadb_x_nat_t_frag *)
                    mhp->ext[SADB_X_EXT_NAT_T_FRAG];
 
+               ipseclog((LOG_DEBUG,
+                       "key_update: type %d, sport = %d, dport = %d\n",
+                       type->sadb_x_nat_t_type_type,
+                       sport->sadb_x_nat_t_port_port,
+                       dport->sadb_x_nat_t_port_port));
+
                if (type)
                        sav->natt_type = type->sadb_x_nat_t_type_type;
                if (sport)
@@ -5151,6 +5197,48 @@
 
        return 0;
 }
+
+/* Just update the IPSEC_NAT_T ports if present */
+static int
+key_set_natt_ports(union sockaddr_union *src, union sockaddr_union *dst,
+                    const struct sadb_msghdr *mhp)
+{
+
+       if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
+               ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+       if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
+               ipseclog((LOG_DEBUG,"update: NAT-T OAr present\n"));
+
+       if ((mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL) &&
+           (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL) &&
+           (mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL)) {
+               struct sadb_x_nat_t_type *type;
+               struct sadb_x_nat_t_port *sport;
+               struct sadb_x_nat_t_port *dport;
+
+               if ((mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type)) ||
+                   (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport)) ||
+                   (mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport))) {
+                       ipseclog((LOG_DEBUG, "key_update: "
+                           "invalid message.\n"));
+                       return -1;
+               }
+
+               sport = (struct sadb_x_nat_t_port *)
+                   mhp->ext[SADB_X_EXT_NAT_T_SPORT];
+               dport = (struct sadb_x_nat_t_port *)
+                   mhp->ext[SADB_X_EXT_NAT_T_DPORT];
+
+               if (sport)
+                       key_porttosaddr(src, 
+                           sport->sadb_x_nat_t_port_port);
+               if (dport)
+                       key_porttosaddr(dst,
+                           dport->sadb_x_nat_t_port_port);
+       }
+
+       return 0;
+}
 #endif
 
 
@@ -5227,6 +5315,10 @@
                                     dst0 + 1, &saidx)) != 0)
                return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+       if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+               return key_senderror(so, m, EINVAL);
+#endif
 
        /* get a SA header */
        if ((sah = key_getsah(&saidx)) == NULL) {
@@ -5288,17 +5380,17 @@
                return key_senderror(so, m, error);
        }
 
+#ifdef IPSEC_NAT_T
+       if ((error = key_handle_natt_info(sav,mhp)) != 0)
+               return key_senderror(so, m, EINVAL);
+#endif /* IPSEC_NAT_T */
+
        /* check SA values to be mature. */



Home | Main Index | Thread Index | Old Index