From 445e6acd205ae32dc7f78583a3bc0b8e7af46bfa Mon Sep 17 00:00:00 2001 From: spz Date: Sun, 5 Sep 2010 06:52:53 +0000 Subject: [PATCH] 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 --- sys/net/pfkeyv2.h | 10 +- sys/netipsec/key.c | 178 ++++++++++++++++++---- sys/netkey/key.c | 357 ++++++++++++++++++++++++++------------------- 3 files changed, 361 insertions(+), 184 deletions(-) diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h index aa23ee3bbb05..f2b977c7d69a 100644 --- a/sys/net/pfkeyv2.h +++ b/sys/net/pfkeyv2.h @@ -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 @@ struct sadb_x_nat_t_frag { #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 --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 914c14528d53..cb2b65c451d2 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -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 -__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 @@ static const int minsize[] = { 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 @@ static const int maxsize[] = { 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 @@ static u_int32_t key_do_getnewspi (struct sadb_spirange *, #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 @@ key_nat_map(struct socket *so, struct mbuf *m, 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 @@ key_nat_map(struct socket *so, struct mbuf *m, 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 @@ key_nat_map(struct socket *so, struct mbuf *m, 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 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, 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 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, 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 @@ key_cmpsaidx( * 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 @@ key_getspi(struct socket *so, struct mbuf *m, 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 @@ key_handle_natt_info(struct secasvar *sav, 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 @@ key_handle_natt_info(struct secasvar *sav, 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 @@ key_handle_natt_info(struct secasvar *sav, 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 @@ key_handle_natt_info(struct secasvar *sav, 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 @@ key_handle_natt_info(struct secasvar *sav, 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 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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. */ if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { KEY_FREESAV(&sav); return key_senderror(so, m, 0); } -#ifdef IPSEC_NAT_T - if ((error = key_handle_natt_info(sav,mhp)) != 0) - return key_senderror(so, m, EINVAL); -#endif /* IPSEC_NAT_T */ - { struct mbuf *n; @@ -5425,6 +5517,11 @@ key_add(struct socket *so, struct mbuf *m, 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 ((newsah = key_getsah(&saidx)) == NULL) { /* create a new SA header */ @@ -5452,17 +5549,17 @@ key_add(struct socket *so, struct mbuf *m, return key_senderror(so, m, error); } +#ifdef IPSEC_NAT_T + if ((error = key_handle_natt_info(newsav, mhp)) != 0) + return key_senderror(so, m, EINVAL); +#endif /* IPSEC_NAT_T */ + /* check SA values to be mature. */ if ((error = key_mature(newsav)) != 0) { KEY_FREESAV(&newsav); return key_senderror(so, m, error); } -#ifdef IPSEC_NAT_T - if ((error = key_handle_natt_info(newsav, mhp)) != 0) - return key_senderror(so, m, EINVAL); -#endif /* IPSEC_NAT_T */ - /* * don't call key_freesav() here, as we would like to keep the SA * in the database on success. @@ -5653,6 +5750,11 @@ key_delete(struct socket *so, struct mbuf *m, 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 */ LIST_FOREACH(sah, &sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) @@ -5718,6 +5820,11 @@ key_delete_all(struct socket *so, struct mbuf *m, 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 + LIST_FOREACH(sah, &sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) continue; @@ -5828,6 +5935,11 @@ key_get(struct socket *so, struct mbuf *m, 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 */ LIST_FOREACH(sah, &sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) @@ -6503,6 +6615,11 @@ key_acquire2(struct socket *so, struct mbuf *m, 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 index */ LIST_FOREACH(sah, &sahtree, chain) { if (sah->state == SADB_SASTATE_DEAD) @@ -7523,7 +7640,8 @@ key_align(struct mbuf *m, struct sadb_msghdr *mhp) case SADB_X_EXT_NAT_T_TYPE: case SADB_X_EXT_NAT_T_SPORT: case SADB_X_EXT_NAT_T_DPORT: - 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: #endif /* duplicate check */ diff --git a/sys/netkey/key.c b/sys/netkey/key.c index e9b085cf9d3f..d3daf581c50f 100644 --- a/sys/netkey/key.c +++ b/sys/netkey/key.c @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.177 2010/03/03 01:13:26 pooka Exp $ */ +/* $NetBSD: key.c,v 1.178 2010/09/05 06:52:53 spz Exp $ */ /* $KAME: key.c,v 1.310 2003/09/08 02:23:44 itojun Exp $ */ /* @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.177 2010/03/03 01:13:26 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.178 2010/09/05 06:52:53 spz Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -201,7 +201,8 @@ static const int minsize[] = { 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 */ #ifdef SADB_X_EXT_TAG sizeof(struct sadb_x_tag), /* SADB_X_TAG */ @@ -231,7 +232,8 @@ static const int maxsize[] = { 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 */ #ifdef SADB_X_EXT_TAG sizeof(struct sadb_x_tag), /* SADB_X_TAG */ @@ -360,6 +362,13 @@ static int key_spddump(struct socket *, struct mbuf *, #ifdef IPSEC_NAT_T static int key_nat_map(struct socket *, struct mbuf *, const struct sadb_msghdr *); +static int key_handle_natt_info (struct secasvar *, + const struct sadb_msghdr *); +static int key_set_natt_ports (struct sockaddr *, struct sockaddr *, + const struct sadb_msghdr *); +#define KEY_SET_NATT_PORTS(saddr, daddr, saidx) \ + key_set_natt_ports((struct sockaddr *)(saddr), \ + (struct sockaddr *)(daddr), (saidx)) #endif static struct mbuf *key_setspddump(int *); static u_int key_getspreqmsglen(struct secpolicy *); @@ -2371,7 +2380,7 @@ key_nat_map(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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 */ @@ -2391,8 +2400,14 @@ key_nat_map(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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); } @@ -2406,7 +2421,8 @@ key_nat_map(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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"); @@ -2418,6 +2434,137 @@ key_nat_map(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) return 0; } + +/* Handle IPSEC_NAT_T info if present */ +static int +key_handle_natt_info(struct secasvar *sav, + 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; + struct sadb_address *iaddr, *raddr; + struct sadb_x_nat_t_frag *frag; + + 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; + } + + 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; + } + + if ((mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) && + (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag))) { + ipseclog((LOG_DEBUG, "key_update: invalid message\n")); + return -1; + } + + 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]; + 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) + KEY_PORTTOSADDR(&sav->sah->saidx.src, + sport->sadb_x_nat_t_port_port); + if (dport) + KEY_PORTTOSADDR(&sav->sah->saidx.dst, + dport->sadb_x_nat_t_port_port); + if (frag) + sav->esp_frag = frag->sadb_x_nat_t_frag_fraglen; + else + sav->esp_frag = IP_MAXPACKET; + } + + return 0; +} + +/* Just update the IPSEC_NAT_T ports if present */ +static int +key_set_natt_ports(struct sockaddr *src, struct sockaddr *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); + else + KEY_PORTTOSADDR(src, 0); + if (dport) + KEY_PORTTOSADDR(dst, + dport->sadb_x_nat_t_port_port); + else + KEY_PORTTOSADDR(dst, 0); + } else { + KEY_PORTTOSADDR(src, 0); + KEY_PORTTOSADDR(dst, 0); + } + + return 0; +} #endif /* IPSEC_NAT_T */ static struct mbuf * @@ -3494,8 +3641,9 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, u_int32_t se 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 }; @@ -3594,7 +3742,8 @@ key_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, u_int32_t se 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 @@ -4958,8 +5107,11 @@ key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure port numbers are set to zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -5217,8 +5369,11 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -5283,74 +5438,17 @@ key_update(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) 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. */ if ((error = key_mature(sav)) != 0) { key_freesav(sav); return key_senderror(so, m, error); } -#ifdef IPSEC_NAT_T - /* - * Handle NAT-T info if present - */ - 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_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; - struct sadb_address *addr; - struct sadb_x_nat_t_frag *frag; - - 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 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))) { - ipseclog((LOG_DEBUG, "key_update: invalid message\n")); - return key_senderror(so, m, EINVAL); - } - - if ((mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) && - (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag))) { - ipseclog((LOG_DEBUG, "key_update: invalid message\n")); - return key_senderror(so, m, EINVAL); - } - - 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]; - frag = (struct sadb_x_nat_t_frag *) - mhp->ext[SADB_X_EXT_NAT_T_FRAG]; - - if (type) - sav->natt_type = type->sadb_x_nat_t_type_type; - if (sport) - KEY_PORTTOSADDR(&sav->sah->saidx.src, - sport->sadb_x_nat_t_port_port); - if (dport) - KEY_PORTTOSADDR(&sav->sah->saidx.dst, - dport->sadb_x_nat_t_port_port); - if (frag) - sav->esp_frag = frag->sadb_x_nat_t_frag_fraglen; - else - sav->esp_frag = IP_MAXPACKET; - } -#endif /* IPSEC_NAT_T */ - { struct mbuf *n; @@ -5473,8 +5571,11 @@ key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -5506,74 +5607,17 @@ key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) return key_senderror(so, m, error); } +#ifdef IPSEC_NAT_T + if ((error = key_handle_natt_info(newsav,mhp)) != 0) + return key_senderror(so, m, EINVAL); +#endif /* IPSEC_NAT_T */ + /* check SA values to be mature. */ if ((error = key_mature(newsav)) != 0) { key_freesav(newsav); return key_senderror(so, m, error); } -#ifdef IPSEC_NAT_T - /* - * Handle NAT-T info if present - */ - if (mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) - printf("add: NAT-T OA 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; - struct sadb_address *addr; - struct sadb_x_nat_t_frag *frag; - - 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_add: " - "invalid message.\n")); - 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))) { - ipseclog((LOG_DEBUG, "key_add: invalid message\n")); - return key_senderror(so, m, EINVAL); - } - - if ((mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) && - (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag))) { - ipseclog((LOG_DEBUG, "key_update: invalid message\n")); - return key_senderror(so, m, EINVAL); - } - - 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]; - frag = (struct sadb_x_nat_t_frag *) - mhp->ext[SADB_X_EXT_NAT_T_FRAG]; - - if (type) - newsav->natt_type = type->sadb_x_nat_t_type_type; - if (sport) - KEY_PORTTOSADDR(&newsav->sah->saidx.src, - sport->sadb_x_nat_t_port_port); - if (dport) - KEY_PORTTOSADDR(&newsav->sah->saidx.dst, - dport->sadb_x_nat_t_port_port); - if (frag) - newsav->esp_frag = frag->sadb_x_nat_t_frag_fraglen; - else - newsav->esp_frag = IP_MAXPACKET; - } -#endif /* IPSEC_NAT_T */ - /* * don't call key_freesav() here, as we would like to keep the SA * in the database on success. @@ -5765,8 +5809,11 @@ key_delete(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -5839,8 +5886,11 @@ key_delete_all(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp, KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -5956,8 +6006,11 @@ key_get(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -6646,8 +6699,11 @@ key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - /* If not using NAT-T, make sure if port number is zero. */ -#ifndef IPSEC_NAT_T +#ifdef IPSEC_NAT_T + if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0) + return key_senderror(so, m, EINVAL); +#else + /* If not using NAT-T, make sure the port numbers are zero. */ KEY_PORTTOSADDR(&saidx.src, 0); KEY_PORTTOSADDR(&saidx.dst, 0); #endif @@ -7735,7 +7791,8 @@ key_align(struct mbuf *m, struct sadb_msghdr *mhp) case SADB_X_EXT_NAT_T_TYPE: case SADB_X_EXT_NAT_T_SPORT: case SADB_X_EXT_NAT_T_DPORT: - 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: #endif #ifdef SADB_X_EXT_TAG