[Swan-dev] pluto: Fix IKEv2 handling of multiple peers behind same NAT

Herbert Xu herbert at gondor.apana.org.au
Thu Apr 23 08:32:29 EEST 2015


The commit 38299da76e4a612ba8b32f8f9537dcdb79b71ecd ("pluto:
fix peer ID checking in ikev2_decode_peer_id_and_certs()" breaks
handling of multiple peers behind the same NAT address.
    
This patch fixes it by removing the ID checks for the responder
case.
    
Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

diff --git a/programs/pluto/ikev2.c b/programs/pluto/ikev2.c
index c7cccd8..fcd094f 100644
--- a/programs/pluto/ikev2.c
+++ b/programs/pluto/ikev2.c
@@ -958,6 +958,7 @@ bool ikev2_decode_peer_id_and_certs(struct msg_digest *md)
 	bool initiator = md->hdr.isa_flags & ISAKMP_FLAGS_v2_MSG_R;
 
 	unsigned int hisID = initiator ? ISAKMP_NEXT_v2IDr : ISAKMP_NEXT_v2IDi;
+	struct state *const st = md->st;
 	struct payload_digest *const id_him = md->chain[hisID];
 	struct connection *c = md->st->st_connection;
 	const pb_stream *id_pbs;
@@ -982,27 +983,34 @@ bool ikev2_decode_peer_id_and_certs(struct msg_digest *md)
 	/* check for certificate requests */
 	ikev2_decode_cr(md, &c->requested_ca);
 
-	if (!same_id(&md->st->st_connection->spd.that.id, &peer) &&
-		id_kind(&md->st->st_connection->spd.that.id) != ID_FROMCERT) {
+	/* Now that we've decoded the ID payload, let's see if we
+	 * need to switch connections.
+	 * We must not switch horses if we initiated:
+	 * - if the initiation was explicit, we'd be ignoring user's intent
+	 * - if opportunistic, we'll lose our HOLD info
+	 */
+	if (initiator) {
+		if (!same_id(&st->st_connection->spd.that.id, &peer) &&
+		    id_kind(&st->st_connection->spd.that.id) != ID_FROMCERT) {
 			char expect[IDTOA_BUF],
 			     found[IDTOA_BUF];
 
-			idtoa(&md->st->st_connection->spd.that.id, expect,
-				sizeof(expect));
+			idtoa(&st->st_connection->spd.that.id, expect,
+			      sizeof(expect));
 			idtoa(&peer, found, sizeof(found));
 			loglog(RC_LOG_SERIOUS,
-				"we require IKEv2 peer to have ID '%s', but peer declares '%s'",
-				expect, found);
-			return FALSE;
-	} else if (id_kind(&md->st->st_connection->spd.that.id) == ID_FROMCERT) {
-		if (id_kind(&peer) != ID_DER_ASN1_DN) {
-			loglog(RC_LOG_SERIOUS, "peer ID is not a certificate type");
+			       "we require IKEv2 peer to have ID '%s', but peer declares '%s'",
+			       expect, found);
 			return FALSE;
+		} else if (id_kind(&st->st_connection->spd.that.id) == ID_FROMCERT) {
+			if (id_kind(&peer) != ID_DER_ASN1_DN) {
+				loglog(RC_LOG_SERIOUS,
+				       "peer ID is not a certificate type");
+				return FALSE;
+			}
+			duplicate_id(&st->st_connection->spd.that.id, &peer);
 		}
-		duplicate_id(&md->st->st_connection->spd.that.id, &peer);
-	}
-
-	if (!initiator) {
+	} else {
 		struct connection *r = NULL;
 		bool fromcert = FALSE;
 		uint16_t auth = md->chain[ISAKMP_NEXT_v2AUTH]->payload.v2a.isaa_type;
@@ -1023,13 +1031,6 @@ bool ikev2_decode_peer_id_and_certs(struct msg_digest *md)
 			DBG(DBG_CONTROL, DBG_log("ikev2 skipping refine_host_connection due to unknown policy"));
 		}
 
-		/*
-		 * Now that we've decoded the ID payload, let's see if we
-		 * need to switch connections.
-		 * We must not switch horses if we initiated:
-		 * - if the initiation was explicit, we'd be ignoring user's intent
-		 * - if opportunistic, we'll lose our HOLD info
-		 */
 		if (auth_policy != LEMPTY) {
 			/* should really return c if no better match found */
 			r = refine_host_connection(md->st, &peer, FALSE /*initiator*/, auth_policy, &fromcert);
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


More information about the Swan-dev mailing list