From 8645c9d72011bfeae72ccecd3edd0f9b295c59c6 Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Wed, 6 Jun 2018 11:11:52 +0200 Subject: ipsec-tools: Apply patches from FreeBSD ports. Source: https://svnweb.freebsd.org/ports/head/security/ipsec-tools/files/ revision 468617. --- ipsec-tools/src/libipsec/libpfkey.h | 2 +- ipsec-tools/src/libipsec/pfkey.c | 33 ++++++++--- ipsec-tools/src/racoon/gssapi.c | 5 ++ ipsec-tools/src/racoon/handler.h | 3 +- ipsec-tools/src/racoon/isakmp.c | 2 + ipsec-tools/src/racoon/isakmp_cfg.c | 4 ++ ipsec-tools/src/racoon/isakmp_frag.c | 102 +++++++++++++++++++++++----------- ipsec-tools/src/racoon/isakmp_inf.c | 1 + ipsec-tools/src/racoon/isakmp_quick.c | 26 +++++++++ ipsec-tools/src/racoon/localconf.c | 3 +- ipsec-tools/src/racoon/nattraversal.c | 5 +- ipsec-tools/src/racoon/pfkey.c | 6 +- 12 files changed, 141 insertions(+), 51 deletions(-) (limited to 'ipsec-tools') diff --git a/ipsec-tools/src/libipsec/libpfkey.h b/ipsec-tools/src/libipsec/libpfkey.h index a213aac7..c05285a2 100644 --- a/ipsec-tools/src/libipsec/libpfkey.h +++ b/ipsec-tools/src/libipsec/libpfkey.h @@ -85,7 +85,7 @@ struct pfkey_send_sa_args { u_int32_t seq; u_int8_t l_natt_type; u_int16_t l_natt_sport, l_natt_dport; - struct sockaddr *l_natt_oa; + struct sockaddr *l_natt_oai, *l_natt_oar; u_int16_t l_natt_frag; u_int8_t ctxdoi, ctxalg; /* Security context DOI and algorithm */ caddr_t ctxstr; /* Security context string */ diff --git a/ipsec-tools/src/libipsec/pfkey.c b/ipsec-tools/src/libipsec/pfkey.c index 3114229e..554952d7 100644 --- a/ipsec-tools/src/libipsec/pfkey.c +++ b/ipsec-tools/src/libipsec/pfkey.c @@ -1335,9 +1335,12 @@ pfkey_send_x1(struct pfkey_send_sa_args *sa_parms) len += sizeof(struct sadb_x_nat_t_type); len += sizeof(struct sadb_x_nat_t_port); len += sizeof(struct sadb_x_nat_t_port); - if (sa_parms->l_natt_oa) + if (sa_parms->l_natt_oai) len += sizeof(struct sadb_address) + - PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)); + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oai)); + if (sa_parms->l_natt_oar) + len += sizeof(struct sadb_address) + + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oar)); #ifdef SADB_X_EXT_NAT_T_FRAG if (sa_parms->l_natt_frag) len += sizeof(struct sadb_x_nat_t_frag); @@ -1452,10 +1455,21 @@ pfkey_send_x1(struct pfkey_send_sa_args *sa_parms) return -1; } - if (sa_parms->l_natt_oa) { - p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA, - sa_parms->l_natt_oa, - (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)), + if (sa_parms->l_natt_oai) { + p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OAI, + sa_parms->l_natt_oai, + (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oai)), + IPSEC_ULPROTO_ANY); + if (!p) { + free(newmsg); + return -1; + } + } + + if (sa_parms->l_natt_oar) { + p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OAR, + sa_parms->l_natt_oar, + (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oar)), IPSEC_ULPROTO_ANY); if (!p) { free(newmsg); @@ -2034,7 +2048,8 @@ pfkey_align(struct sadb_msg *msg, caddr_t *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: #endif #ifdef SADB_X_EXT_TAG case SADB_X_EXT_TAG: @@ -2592,7 +2607,7 @@ pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src, psaa.l_natt_type = l_natt_type; psaa.l_natt_sport = l_natt_sport; psaa.l_natt_dport = l_natt_dport; - psaa.l_natt_oa = l_natt_oa; + psaa.l_natt_oar = l_natt_oa; psaa.l_natt_frag = l_natt_frag; return pfkey_send_update2(&psaa); @@ -2667,7 +2682,7 @@ pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src, psaa.l_natt_type = l_natt_type; psaa.l_natt_sport = l_natt_sport; psaa.l_natt_dport = l_natt_dport; - psaa.l_natt_oa = l_natt_oa; + psaa.l_natt_oai = l_natt_oa; psaa.l_natt_frag = l_natt_frag; return pfkey_send_add2(&psaa); diff --git a/ipsec-tools/src/racoon/gssapi.c b/ipsec-tools/src/racoon/gssapi.c index e64b2015..7edcf4f6 100644 --- a/ipsec-tools/src/racoon/gssapi.c +++ b/ipsec-tools/src/racoon/gssapi.c @@ -192,6 +192,11 @@ gssapi_init(struct ph1handle *iph1) gss_name_t princ, canon_princ; OM_uint32 maj_stat, min_stat; + if (iph1->rmconf == NULL) { + plog(LLV_ERROR, LOCATION, NULL, "no remote config\n"); + return -1; + } + gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); if (gps == NULL) { plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); diff --git a/ipsec-tools/src/racoon/handler.h b/ipsec-tools/src/racoon/handler.h index 45d596e2..f4e6afd0 100644 --- a/ipsec-tools/src/racoon/handler.h +++ b/ipsec-tools/src/racoon/handler.h @@ -1,4 +1,4 @@ -/* $NetBSD: handler.h,v 1.25 2010/11/17 10:40:41 tteras Exp $ */ +/* $NetBSD: handler.h,v 1.26 2017/01/24 19:23:56 christos Exp $ */ /* Id: handler.h,v 1.19 2006/02/25 08:25:12 manubsd Exp */ @@ -141,6 +141,7 @@ struct ph1handle { #endif #ifdef ENABLE_FRAG int frag; /* IKE phase 1 fragmentation */ + int frag_last_index; struct isakmp_frag_item *frag_chain; /* Received fragments */ #endif diff --git a/ipsec-tools/src/racoon/isakmp.c b/ipsec-tools/src/racoon/isakmp.c index 2672f7ae..f9291c86 100644 --- a/ipsec-tools/src/racoon/isakmp.c +++ b/ipsec-tools/src/racoon/isakmp.c @@ -1069,6 +1069,7 @@ isakmp_ph1begin_i(rmconf, remote, local) iph1->frag = 1; else iph1->frag = 0; + iph1->frag_last_index = 0; iph1->frag_chain = NULL; #endif iph1->approval = NULL; @@ -1173,6 +1174,7 @@ isakmp_ph1begin_r(msg, remote, local, etype) #endif #ifdef ENABLE_FRAG iph1->frag = 0; + iph1->frag_last_index = 0; iph1->frag_chain = NULL; #endif iph1->approval = NULL; diff --git a/ipsec-tools/src/racoon/isakmp_cfg.c b/ipsec-tools/src/racoon/isakmp_cfg.c index 67464590..660a32fe 100644 --- a/ipsec-tools/src/racoon/isakmp_cfg.c +++ b/ipsec-tools/src/racoon/isakmp_cfg.c @@ -38,7 +38,9 @@ #include #include +#if __FreeBSD_version >= 900007 #include +#endif #if defined(__APPLE__) && defined(__MACH__) #include #endif @@ -1663,6 +1665,7 @@ isakmp_cfg_accounting_system(port, raddr, usr, inout) char *usr; int inout; { +#if __FreeBSD_version >= 900007 int error = 0; struct utmpx ut; char addr[NI_MAXHOST]; @@ -1706,6 +1709,7 @@ isakmp_cfg_accounting_system(port, raddr, usr, inout) plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n"); break; } +#endif return 0; } diff --git a/ipsec-tools/src/racoon/isakmp_frag.c b/ipsec-tools/src/racoon/isakmp_frag.c index ebba34b4..868ac943 100644 --- a/ipsec-tools/src/racoon/isakmp_frag.c +++ b/ipsec-tools/src/racoon/isakmp_frag.c @@ -1,4 +1,4 @@ -/* $NetBSD: isakmp_frag.c,v 1.5 2009/04/22 11:24:20 tteras Exp $ */ +/* $NetBSD: isakmp_frag.c,v 1.7 2017/07/23 05:40:27 christos Exp $ */ /* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp */ @@ -173,6 +173,43 @@ vendorid_frag_cap(gen) return ntohl(hp[MD5_DIGEST_LENGTH / sizeof(*hp)]); } +static int +isakmp_frag_insert(struct ph1handle *iph1, struct isakmp_frag_item *item) +{ + struct isakmp_frag_item *pitem = NULL; + struct isakmp_frag_item *citem = iph1->frag_chain; + + /* no frag yet, just insert at beginning of list */ + if (iph1->frag_chain == NULL) { + iph1->frag_chain = item; + return 0; + } + + do { + /* duplicate fragment number, abort (CVE-2016-10396) */ + if (citem->frag_num == item->frag_num) + return -1; + + /* need to insert before current item */ + if (citem->frag_num > item->frag_num) { + if (pitem != NULL) + pitem->frag_next = item; + else + /* insert at the beginning of the list */ + iph1->frag_chain = item; + item->frag_next = citem; + return 0; + } + + pitem = citem; + citem = citem->frag_next; + } while (citem != NULL); + + /* we reached the end of the list, insert */ + pitem->frag_next = item; + return 0; +} + int isakmp_frag_extract(iph1, msg) struct ph1handle *iph1; @@ -224,39 +261,43 @@ isakmp_frag_extract(iph1, msg) item->frag_next = NULL; item->frag_packet = buf; - /* Look for the last frag while inserting the new item in the chain */ - if (item->frag_last) - last_frag = item->frag_num; - - if (iph1->frag_chain == NULL) { - iph1->frag_chain = item; - } else { - struct isakmp_frag_item *current; - - current = iph1->frag_chain; - while (current->frag_next) { - if (current->frag_last) - last_frag = item->frag_num; - current = current->frag_next; + /* Check for the last frag before inserting the new item in the chain */ + if (item->frag_last) { + /* if we have the last fragment, indices must match */ + if (iph1->frag_last_index != 0 && + item->frag_last != iph1->frag_last_index) { + plog(LLV_ERROR, LOCATION, NULL, + "Repeated last fragment index mismatch\n"); + racoon_free(item); + vfree(buf); + return -1; } - current->frag_next = item; + + last_frag = iph1->frag_last_index = item->frag_num; } - /* If we saw the last frag, check if the chain is complete */ + /* insert fragment into chain */ + if (isakmp_frag_insert(iph1, item) == -1) { + plog(LLV_ERROR, LOCATION, NULL, + "Repeated fragment index mismatch\n"); + racoon_free(item); + vfree(buf); + return -1; + } + + /* If we saw the last frag, check if the chain is complete + * we have a sorted list now, so just walk through */ if (last_frag != 0) { + item = iph1->frag_chain; for (i = 1; i <= last_frag; i++) { - item = iph1->frag_chain; - do { - if (item->frag_num == i) - break; - item = item->frag_next; - } while (item != NULL); - + if (item->frag_num != i) + break; + item = item->frag_next; if (item == NULL) /* Not found */ break; } - if (item != NULL) /* It is complete */ + if (i > last_frag) /* It is complete */ return 1; } @@ -291,15 +332,9 @@ isakmp_frag_reassembly(iph1) } data = buf->v; + item = iph1->frag_chain; for (i = 1; i <= frag_count; i++) { - item = iph1->frag_chain; - do { - if (item->frag_num == i) - break; - item = item->frag_next; - } while (item != NULL); - - if (item == NULL) { + if (item->frag_num != i) { plog(LLV_ERROR, LOCATION, NULL, "Missing fragment #%d\n", i); vfree(buf); @@ -308,6 +343,7 @@ isakmp_frag_reassembly(iph1) } memcpy(data, item->frag_packet->v, item->frag_packet->l); data += item->frag_packet->l; + item = item->frag_next; } out: diff --git a/ipsec-tools/src/racoon/isakmp_inf.c b/ipsec-tools/src/racoon/isakmp_inf.c index 99daffb3..b81d460a 100644 --- a/ipsec-tools/src/racoon/isakmp_inf.c +++ b/ipsec-tools/src/racoon/isakmp_inf.c @@ -720,6 +720,7 @@ isakmp_info_send_nx(isakmp, remote, local, type, data) #endif #ifdef ENABLE_FRAG iph1->frag = 0; + iph1->frag_last_index = 0; iph1->frag_chain = NULL; #endif diff --git a/ipsec-tools/src/racoon/isakmp_quick.c b/ipsec-tools/src/racoon/isakmp_quick.c index fa957ebc..77d126dd 100644 --- a/ipsec-tools/src/racoon/isakmp_quick.c +++ b/ipsec-tools/src/racoon/isakmp_quick.c @@ -2390,6 +2390,32 @@ get_proposal_r(iph2) spidx.src.ss_family, spidx.dst.ss_family, _XIDT(iph2->id_p),idi2type); } +#ifdef ENABLE_NATT + if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) { + u_int16_t port; + + port = extract_port(&spidx.src); + memcpy(&spidx.src, iph2->ph1->remote, + sysdep_sa_len(iph2->ph1->remote)); + set_port(&spidx.src, port); + switch (spidx.src.ss_family) { + case AF_INET: + spidx.prefs = sizeof(struct in_addr) << 3; + break; +#ifdef INET6 + case AF_INET6: + spidx.prefs = sizeof(struct in6_addr) << 3; + break; +#endif + default: + spidx.prefs = 0; + break; + } + plog(LLV_DEBUG, LOCATION, + NULL, "use NAT address %s as src\n", + saddr2str((struct sockaddr *)&spidx.src)); + } +#endif } else { plog(LLV_DEBUG, LOCATION, NULL, "get a source address of SP index from Phase 1" diff --git a/ipsec-tools/src/racoon/localconf.c b/ipsec-tools/src/racoon/localconf.c index a512953b..f38ee285 100644 --- a/ipsec-tools/src/racoon/localconf.c +++ b/ipsec-tools/src/racoon/localconf.c @@ -207,7 +207,8 @@ getpsk(str, len) if (*p == '\0') continue; /* no 2nd parameter */ p--; - if (strncmp(buf, str, len) == 0 && buf[len] == '\0') { + if (strcmp(buf, "*") == 0 + || (strncmp(buf, str, len) == 0 && buf[len] == '\0')) { p++; keylen = 0; for (q = p; *q != '\0' && *q != '\n'; q++) diff --git a/ipsec-tools/src/racoon/nattraversal.c b/ipsec-tools/src/racoon/nattraversal.c index b04cc1b5..c36d26f8 100644 --- a/ipsec-tools/src/racoon/nattraversal.c +++ b/ipsec-tools/src/racoon/nattraversal.c @@ -436,10 +436,7 @@ natt_keepalive_add_ph1 (struct ph1handle *iph1) { int ret = 0; - /* Should only the NATed host send keepalives? - If yes, add '(iph1->natt_flags & NAT_DETECTED_ME)' - to the following condition. */ - if (iph1->natt_flags & NAT_DETECTED && + if (iph1->natt_flags & NAT_DETECTED_ME && ! (iph1->natt_flags & NAT_KA_QUEUED)) { ret = natt_keepalive_add (iph1->local, iph1->remote); if (ret == 0) diff --git a/ipsec-tools/src/racoon/pfkey.c b/ipsec-tools/src/racoon/pfkey.c index d00b166d..68879992 100644 --- a/ipsec-tools/src/racoon/pfkey.c +++ b/ipsec-tools/src/racoon/pfkey.c @@ -1190,7 +1190,10 @@ pk_sendupdate(iph2) sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type; sa_args.l_natt_sport = extract_port(iph2->ph1->remote); sa_args.l_natt_dport = extract_port(iph2->ph1->local); - sa_args.l_natt_oa = iph2->natoa_src; + /* if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) */ + sa_args.l_natt_oai = iph2->natoa_dst; + /* if (iph2->ph1->natt_flags & NAT_DETECTED_ME) */ + sa_args.l_natt_oar = iph2->natoa_src; #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif @@ -1477,7 +1480,6 @@ pk_sendadd(iph2) sa_args.l_natt_type = UDP_ENCAP_ESPINUDP; sa_args.l_natt_sport = extract_port(iph2->ph1->local); sa_args.l_natt_dport = extract_port(iph2->ph1->remote); - sa_args.l_natt_oa = iph2->natoa_dst; #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif -- cgit v1.2.3