[PATCH v2 08/15] ipsec-tools: Apply patches from FreeBSD ports.

Christian Mauderer christian.mauderer at embedded-brains.de
Thu Aug 2 08:55:40 UTC 2018


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(-)

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 <sys/socket.h>
 #include <sys/queue.h>
 
+#if __FreeBSD_version >= 900007
 #include <utmpx.h>
+#endif
 #if defined(__APPLE__) && defined(__MACH__)
 #include <util.h>
 #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
-- 
2.13.7




More information about the devel mailing list