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;
}
/*