Blob Blame History Raw
diff --git a/programs/pluto/ikev1_main.c b/programs/pluto/ikev1_main.c
index de20a83..31d959b 100644
--- a/programs/pluto/ikev1_main.c
+++ b/programs/pluto/ikev1_main.c
@@ -2983,13 +2983,12 @@ bool accept_delete(struct msg_digest *md,
 			 * IPSEC (ESP/AH)
 			 */
 			ipsec_spi_t spi;	/* network order */
-			bool bogus;
-			struct state *dst;
 
 			if (!in_raw(&spi, sizeof(spi), &p->pbs, "SPI"))
 				return self_delete;
 
-			dst = find_phase2_state_to_delete(st,
+			bool bogus;
+			struct state *dst = find_phase2_state_to_delete(st,
 							d->isad_protoid,
 							spi,
 							&bogus);
@@ -2997,14 +2996,19 @@ bool accept_delete(struct msg_digest *md,
 			passert(dst != st);	/* st is an IKE SA */
 			if (dst == NULL) {
 				loglog(RC_LOG_SERIOUS,
-					"ignoring Delete SA payload: %s SA(0x%08" PRIx32 ") not found (%s)",
+					"ignoring Delete SA payload: %s SA(0x%08" PRIx32 ") not found (maybe expired)",
 					enum_show(&protocol_names,
 						d->isad_protoid),
-					ntohl(spi),
-					bogus ?
-						"our SPI - bogus implementation" :
-						"maybe expired");
+					ntohl(spi));
 			} else {
+				if (bogus) {
+					loglog(RC_LOG_SERIOUS,
+						"warning: Delete SA payload: %s SA(0x%08" PRIx32 ") is our own SPI (bogus implementation) - deleting anyway",
+						enum_show(&protocol_names,
+							d->isad_protoid),
+						ntohl(spi));
+				}
+
 				struct connection *rc = dst->st_connection;
 				struct connection *oldc = cur_connection;
 
diff --git a/programs/pluto/state.c b/programs/pluto/state.c
index b2eac62..c5d4484 100644
--- a/programs/pluto/state.c
+++ b/programs/pluto/state.c
@@ -1537,37 +1537,52 @@ struct state *find_likely_sender(size_t packet_len, u_char *packet)
 	return NULL;
 }
 
+/*
+ * find_phase2_state_to_delete: find an AH or ESP SA to delete
+ *
+ * We are supposed to be given the other side's SPI.
+ * Certain CISCO implementations send our side's SPI instead.
+ * We'll accept this, but mark it as bogus.
+ */
 struct state *find_phase2_state_to_delete(const struct state *p1st,
 					  u_int8_t protoid,
 					  ipsec_spi_t spi,
 					  bool *bogus)
 {
-	struct state *st;
+	struct state  *bogusst = NULL;
 	int i;
 
 	*bogus = FALSE;
 	for (i = 0; i < STATE_TABLE_SIZE; i++) {
+		struct state *st;
+
 		FOR_EACH_ENTRY(st, i, {
 			if (IS_IPSEC_SA_ESTABLISHED(st->st_state) &&
 				p1st->st_connection->host_pair ==
 				st->st_connection->host_pair &&
 				same_peer_ids(p1st->st_connection,
-					st->st_connection, NULL)) {
+					st->st_connection, NULL))
+			{
 				struct ipsec_proto_info *pr =
 					protoid == PROTO_IPSEC_AH ?
 					&st->st_ah : &st->st_esp;
 
 				if (pr->present) {
-					if (pr->attrs.spi == spi)
+					if (pr->attrs.spi == spi) {
+						*bogus = FALSE;
 						return st;
+					}
 
-					if (pr->our_spi == spi)
+					if (pr->our_spi == spi) {
 						*bogus = TRUE;
+						bogusst = st;
+						/* don't return! */
+					}
 				}
 			}
 		});
 	}
-	return NULL;
+	return bogusst;
 }
 
 /*