Avoid expectiation failure with crossing streams
Resolves: RHEL-73236 Signed-off-by: Daiki Ueno <dueno@redhat.com>
This commit is contained in:
parent
5ff2eaede3
commit
1394b8e496
737
libreswan-5.1-pexpect-negotiating-ike-sa.patch
Normal file
737
libreswan-5.1-pexpect-negotiating-ike-sa.patch
Normal file
@ -0,0 +1,737 @@
|
||||
From d421aeb263d81bacb92e392c65910054f71f9843 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cagney <cagney@gnu.org>
|
||||
Date: Thu, 16 Jan 2025 19:28:00 -0500
|
||||
Subject: [PATCH 1/4] revival: move state specific pexpects to
|
||||
scheduled_{ike,child}_revival()
|
||||
|
||||
---
|
||||
programs/pluto/revival.c | 101 +++++++++++++++++++--------------------
|
||||
programs/pluto/revival.h | 4 +-
|
||||
programs/pluto/routing.c | 21 ++++++--
|
||||
3 files changed, 66 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/programs/pluto/revival.c b/programs/pluto/revival.c
|
||||
index 0da0d7e4d2..8a2c779c18 100644
|
||||
--- a/programs/pluto/revival.c
|
||||
+++ b/programs/pluto/revival.c
|
||||
@@ -191,58 +191,9 @@ static void schedule_revival_event(struct connection *c, struct logger *logger,
|
||||
(impair.revival ? "revival" : NULL), logger);
|
||||
}
|
||||
|
||||
-bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/,
|
||||
- const char *subplot, struct logger *logger)
|
||||
+static bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/,
|
||||
+ const char *subplot, struct logger *logger)
|
||||
{
|
||||
- if (st != NULL) {
|
||||
- /*
|
||||
- * pexpect() ST is the owner. Routing should never
|
||||
- * call when it isn't.
|
||||
- */
|
||||
- if (IS_CHILD_SA(st)) {
|
||||
- if (c->negotiating_child_sa != SOS_NOBODY &&
|
||||
- c->negotiating_child_sa != st->st_serialno) {
|
||||
- /*
|
||||
- * There's a newer SA playing with the routing.
|
||||
- * Presumably this is an old Child SA that is in the
|
||||
- * process of being rekeyed or replaced.
|
||||
- */
|
||||
- llog_pexpect(st->logger, HERE,
|
||||
- "revival: skipping, .negotiating_child_sa "PRI_SO" is not us",
|
||||
- pri_so(c->negotiating_child_sa));
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (c->established_child_sa != SOS_NOBODY &&
|
||||
- c->established_child_sa != st->st_serialno) {
|
||||
- /* should be covered by above */
|
||||
- llog_pexpect(st->logger, HERE,
|
||||
- "revival: skipping, .established_child_sa "PRI_SO" is not us",
|
||||
- pri_so(c->established_child_sa));
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (IS_IKE_SA(st)) {
|
||||
- if (c->negotiating_ike_sa != SOS_NOBODY &&
|
||||
- c->negotiating_ike_sa != st->st_serialno) {
|
||||
- /* should be covered by above */
|
||||
- llog_pexpect(st->logger, HERE,
|
||||
- "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us",
|
||||
- pri_so(c->negotiating_ike_sa));
|
||||
- return false;
|
||||
- }
|
||||
- if (c->established_ike_sa != SOS_NOBODY &&
|
||||
- c->established_ike_sa != st->st_serialno) {
|
||||
- /* should be covered by above */
|
||||
- llog_pexpect(st->logger, HERE,
|
||||
- "revival: skipping, .established_ike_sa "PRI_SO" is is not us",
|
||||
- pri_so(c->established_ike_sa));
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (!revival_plausable(c, logger)) {
|
||||
return false;
|
||||
}
|
||||
@@ -275,14 +226,58 @@ bool scheduled_revival(struct connection *c, struct state *st/*can be NULL*/,
|
||||
|
||||
}
|
||||
|
||||
+bool scheduled_connection_revival(struct connection *c, const char *subplot)
|
||||
+{
|
||||
+ return scheduled_revival(c, NULL, subplot, c->logger);
|
||||
+}
|
||||
+
|
||||
bool scheduled_child_revival(struct child_sa *child, const char *subplot)
|
||||
{
|
||||
- return scheduled_revival(child->sa.st_connection, &child->sa, subplot, child->sa.logger);
|
||||
+ struct connection *c = child->sa.st_connection;
|
||||
+ if (c->negotiating_child_sa != SOS_NOBODY &&
|
||||
+ c->negotiating_child_sa != child->sa.st_serialno) {
|
||||
+ /*
|
||||
+ * There's a newer SA playing with the routing.
|
||||
+ * Presumably this is an old Child SA that is in the
|
||||
+ * process of being rekeyed or replaced.
|
||||
+ */
|
||||
+ llog_pexpect(child->sa.logger, HERE,
|
||||
+ "revival: skipping, .negotiating_child_sa "PRI_SO" is not us",
|
||||
+ pri_so(c->negotiating_child_sa));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (c->established_child_sa != SOS_NOBODY &&
|
||||
+ c->established_child_sa != child->sa.st_serialno) {
|
||||
+ /* should be covered by above */
|
||||
+ llog_pexpect(child->sa.logger, HERE,
|
||||
+ "revival: skipping, .established_child_sa "PRI_SO" is not us",
|
||||
+ pri_so(c->established_child_sa));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return scheduled_revival(c, &child->sa, subplot, child->sa.logger);
|
||||
}
|
||||
|
||||
bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot)
|
||||
{
|
||||
- return scheduled_revival(ike->sa.st_connection, &ike->sa, subplot, ike->sa.logger);
|
||||
+ struct connection *c = ike->sa.st_connection;
|
||||
+ if (c->negotiating_ike_sa != SOS_NOBODY &&
|
||||
+ c->negotiating_ike_sa != ike->sa.st_serialno) {
|
||||
+ /* should be covered by above */
|
||||
+ llog_pexpect(ike->sa.logger, HERE,
|
||||
+ "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us",
|
||||
+ pri_so(c->negotiating_ike_sa));
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (c->established_ike_sa != SOS_NOBODY &&
|
||||
+ c->established_ike_sa != ike->sa.st_serialno) {
|
||||
+ /* should be covered by above */
|
||||
+ llog_pexpect(ike->sa.logger, HERE,
|
||||
+ "revival: skipping, .established_ike_sa "PRI_SO" is is not us",
|
||||
+ pri_so(c->established_ike_sa));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return scheduled_revival(c, &ike->sa, subplot, ike->sa.logger);
|
||||
}
|
||||
|
||||
void revive_connection(struct connection *c, const char *subplot,
|
||||
diff --git a/programs/pluto/revival.h b/programs/pluto/revival.h
|
||||
index dad6705301..13b00980dd 100644
|
||||
--- a/programs/pluto/revival.h
|
||||
+++ b/programs/pluto/revival.h
|
||||
@@ -25,14 +25,12 @@ struct timer_event;
|
||||
void revive_connection(struct connection *c, const char *subplot,
|
||||
const threadtime_t *inception);
|
||||
|
||||
-bool scheduled_revival(struct connection *c, struct state *st, /*could-be-NULL*/
|
||||
- const char *subplot, struct logger *logger);
|
||||
-
|
||||
/*
|
||||
* As in the SA's connection should be kept up so the call scheduled a
|
||||
* revival. Caller should adjust routing accordingly.
|
||||
*/
|
||||
|
||||
+bool scheduled_connection_revival(struct connection *c, const char *subplot);
|
||||
bool scheduled_child_revival(struct child_sa *child, const char *subplot);
|
||||
bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot);
|
||||
|
||||
diff --git a/programs/pluto/routing.c b/programs/pluto/routing.c
|
||||
index 91115ab081..dd9b39721c 100644
|
||||
--- a/programs/pluto/routing.c
|
||||
+++ b/programs/pluto/routing.c
|
||||
@@ -104,14 +104,27 @@ static bool connection_cannot_die(enum routing_event event,
|
||||
struct logger *logger,
|
||||
const struct routing_annex *e)
|
||||
{
|
||||
- struct state *st = (e->child != NULL && (*e->child) != NULL ? &(*e->child)->sa :
|
||||
- e->ike != NULL && (*e->ike) != NULL ? &(*e->ike)->sa :
|
||||
- NULL);
|
||||
const char *subplot = (event == CONNECTION_TEARDOWN_IKE ? e->story :
|
||||
event == CONNECTION_TEARDOWN_CHILD ? e->story :
|
||||
event == CONNECTION_RESCHEDULE ? e->story :
|
||||
"???");
|
||||
- return scheduled_revival(c, st, subplot, logger);
|
||||
+ if (e->child != NULL) {
|
||||
+ struct child_sa *child = (*e->child);
|
||||
+ if (child != NULL) {
|
||||
+ PEXPECT(logger, child->sa.st_connection == c);
|
||||
+ return scheduled_child_revival(child, subplot);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (e->ike != NULL) {
|
||||
+ struct ike_sa *ike = (*e->ike);
|
||||
+ if (ike != NULL) {
|
||||
+ PEXPECT(logger, ike->sa.st_connection == c);
|
||||
+ return scheduled_ike_revival(ike, subplot);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return scheduled_connection_revival(c, subplot);
|
||||
}
|
||||
|
||||
static void jam_sa(struct jambuf *buf, struct state *st, const char **sep)
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
||||
From e474d36c43798898fa89d28ba302868399329f95 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cagney <cagney@gnu.org>
|
||||
Date: Thu, 16 Jan 2025 20:20:24 -0500
|
||||
Subject: [PATCH 2/4] revival: don't expect the IKE SA have
|
||||
.{established,negotiating}_ike_sa
|
||||
|
||||
A crossing stream where this end initiated the connection's
|
||||
IKE SA but is then crossed by the peer establishing the
|
||||
connection's IKE SA only to connswitch to another
|
||||
connection for the Child SA - leaves .negotiating_sa
|
||||
but nothing else.
|
||||
|
||||
see #1989 EXPECTATION FAILED: revival: skipping, .negotiating_ike_sa is not us
|
||||
---
|
||||
programs/pluto/revival.c | 25 +++++++++++++++----------
|
||||
1 file changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/programs/pluto/revival.c b/programs/pluto/revival.c
|
||||
index 8a2c779c18..fe76d1039e 100644
|
||||
--- a/programs/pluto/revival.c
|
||||
+++ b/programs/pluto/revival.c
|
||||
@@ -261,21 +261,26 @@ bool scheduled_child_revival(struct child_sa *child, const char *subplot)
|
||||
bool scheduled_ike_revival(struct ike_sa *ike, const char *subplot)
|
||||
{
|
||||
struct connection *c = ike->sa.st_connection;
|
||||
- if (c->negotiating_ike_sa != SOS_NOBODY &&
|
||||
- c->negotiating_ike_sa != ike->sa.st_serialno) {
|
||||
- /* should be covered by above */
|
||||
+ if (c->routing_sa != ike->sa.st_serialno) {
|
||||
llog_pexpect(ike->sa.logger, HERE,
|
||||
- "revival: skipping, .negotiating_ike_sa "PRI_SO" is is not us",
|
||||
- pri_so(c->negotiating_ike_sa));
|
||||
+ "revival: skipping, .routing_sa "PRI_SO" is is not us",
|
||||
+ pri_so(c->routing_sa));
|
||||
return false;
|
||||
}
|
||||
+ if (c->negotiating_ike_sa != SOS_NOBODY &&
|
||||
+ c->negotiating_ike_sa != ike->sa.st_serialno) {
|
||||
+ /*
|
||||
+ * For instance, crossing stream establishes IKE SA,
|
||||
+ * but some other Child SA, leaving .routing_sa
|
||||
+ * hanging.
|
||||
+ */
|
||||
+ ldbg(ike->sa.logger, "revival: .negotiating_ike_sa "PRI_SO" is is not us",
|
||||
+ pri_so(c->negotiating_ike_sa));
|
||||
+ }
|
||||
if (c->established_ike_sa != SOS_NOBODY &&
|
||||
c->established_ike_sa != ike->sa.st_serialno) {
|
||||
- /* should be covered by above */
|
||||
- llog_pexpect(ike->sa.logger, HERE,
|
||||
- "revival: skipping, .established_ike_sa "PRI_SO" is is not us",
|
||||
- pri_so(c->established_ike_sa));
|
||||
- return false;
|
||||
+ ldbg(ike->sa.logger, "revival: .established_ike_sa "PRI_SO" is is not us",
|
||||
+ pri_so(c->established_ike_sa));
|
||||
}
|
||||
return scheduled_revival(c, &ike->sa, subplot, ike->sa.logger);
|
||||
}
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
||||
From c70b4bf00dee27d35a438bdac9ed78ea76127384 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cagney <cagney@gnu.org>
|
||||
Date: Thu, 16 Jan 2025 17:22:09 -0500
|
||||
Subject: [PATCH 3/4] testing: add WIP
|
||||
crossing-streams-23-conswitch-ike-sa-init-ikev2, see #1989
|
||||
|
||||
---
|
||||
testing/pluto/TESTLIST | 1 +
|
||||
.../01-east-init.sh | 11 ++
|
||||
.../02-west-init.sh | 9 ++
|
||||
.../03-west-ike-sa-init.sh | 13 +++
|
||||
.../04-east-establish.sh | 6 ++
|
||||
.../05-west-crossing-stream.sh | 9 ++
|
||||
.../description.txt | 34 ++++++
|
||||
.../east.console.txt | 74 +++++++++++++
|
||||
.../final.sh | 6 ++
|
||||
.../ipsec.conf | 32 ++++++
|
||||
.../ipsec.secrets | 1 +
|
||||
.../west.console.txt | 101 ++++++++++++++++++
|
||||
12 files changed, 297 insertions(+)
|
||||
create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh
|
||||
create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt
|
||||
create mode 100755 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets
|
||||
create mode 100644 testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt
|
||||
|
||||
diff --git a/testing/pluto/TESTLIST b/testing/pluto/TESTLIST
|
||||
index 49d65fb534..24697f3786 100644
|
||||
--- a/testing/pluto/TESTLIST
|
||||
+++ b/testing/pluto/TESTLIST
|
||||
@@ -1562,6 +1562,7 @@ kvmplutotest crossing-streams-20-peer-restarts-ondemand-ike-auth good github/163
|
||||
|
||||
kvmplutotest crossing-streams-21-second-child-crypto-ikev2 good
|
||||
kvmplutotest crossing-streams-22-ikev2-ipsec-interface wip github:557
|
||||
+kvmplutotest crossing-streams-23-conswitch-ike-sa-init-ikev2 wip github/1989
|
||||
|
||||
# uses the kernel-pfkeyv2.c code
|
||||
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh
|
||||
new file mode 100755
|
||||
index 0000000000..5eac31179d
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/01-east-init.sh
|
||||
@@ -0,0 +1,11 @@
|
||||
+/testing/guestbin/swan-prep --nokey
|
||||
+
|
||||
+../../guestbin/ifconfig.sh eth0 add 192.0.20.254/24
|
||||
+
|
||||
+ipsec start
|
||||
+../../guestbin/wait-until-pluto-started
|
||||
+
|
||||
+ipsec whack --impair suppress_retransmits
|
||||
+
|
||||
+ipsec add a
|
||||
+ipsec add b
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh
|
||||
new file mode 100755
|
||||
index 0000000000..3690498351
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/02-west-init.sh
|
||||
@@ -0,0 +1,9 @@
|
||||
+/testing/guestbin/swan-prep --nokey
|
||||
+ipsec start
|
||||
+../../guestbin/wait-until-pluto-started
|
||||
+
|
||||
+ipsec whack --impair suppress_retransmits
|
||||
+
|
||||
+# note order
|
||||
+ipsec add a
|
||||
+ipsec add b
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh
|
||||
new file mode 100644
|
||||
index 0000000000..65837088f5
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/03-west-ike-sa-init.sh
|
||||
@@ -0,0 +1,13 @@
|
||||
+# Initiate "a" with all packets blocked.
|
||||
+#
|
||||
+# This will create the negotiating IKE SA #1, and then hang.
|
||||
+
|
||||
+ipsec whack --impair block_outbound:yes
|
||||
+ipsec up a --asynchronous
|
||||
+../../guestbin/wait-for-pluto.sh --match '"a" #1: IMPAIR: blocking outbound message 1'
|
||||
+../../guestbin/wait-for-pluto.sh --match '"a" #1: sent IKE_SA_INIT request'
|
||||
+
|
||||
+# With connection "a"'s IKE SA #1 stuck, unblock so that the peer's
|
||||
+# IKE SA #2, which will cross "a", can establish
|
||||
+
|
||||
+ipsec whack --impair block_outbound:no
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh
|
||||
new file mode 100644
|
||||
index 0000000000..668613881b
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/04-east-establish.sh
|
||||
@@ -0,0 +1,6 @@
|
||||
+# Initiate "b" from EAST.
|
||||
+#
|
||||
+# On WEST this is will match and establish connection "a" with IKE SA
|
||||
+# #2, and then switch to connection "b" for Child SA #3.
|
||||
+
|
||||
+ipsec up b
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh
|
||||
new file mode 100644
|
||||
index 0000000000..dc8387a82f
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/05-west-crossing-stream.sh
|
||||
@@ -0,0 +1,9 @@
|
||||
+# confirm that the peer's IKE SA established "a", and then the peer's
|
||||
+# Child SA needed to switch to "b" before establishing.
|
||||
+
|
||||
+../../guestbin/wait-for-pluto.sh --match '"a" #2: responder established IKE SA'
|
||||
+../../guestbin/wait-for-pluto.sh --match '"a" #3: switched to "b"'
|
||||
+../../guestbin/wait-for-pluto.sh --match '"b" #3: responder established Child SA using #2'
|
||||
+
|
||||
+# this is where pluto realises that the stream crossed
|
||||
+../../guestbin/wait-for-pluto.sh --match '#1: dropping negotiation'
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt
|
||||
new file mode 100644
|
||||
index 0000000000..52806b90d5
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/description.txt
|
||||
@@ -0,0 +1,34 @@
|
||||
+IKE exchange crosses, initiator conswitches peer's child leaving local ike hanging
|
||||
+
|
||||
+each end has two connections that can share their IKE SA
|
||||
+
|
||||
+- WEST sends "a":IKE_SA_INIT to EAST
|
||||
+ - creates IKE SA #1
|
||||
+ - initiator sets "a".{routing,negotiating}_ike_sa to #1
|
||||
+
|
||||
+- EAST sends "b":IKE_SA_INIT to WEST
|
||||
+
|
||||
+- WEST responds to EAST'S "b":IKE_SA_INIT
|
||||
+ - creates IKE_SA #2 using connection "a"
|
||||
+ - responder leaves "a".{routing,negotiating}_ike_sa et.al. untouched
|
||||
+
|
||||
+- EAST sends "b":IKE_AUTH to WEST
|
||||
+
|
||||
+- WEST responds to EAST's "b":IKE_AUTH
|
||||
+ IKE
|
||||
+ - establishes IKE SA #2
|
||||
+ - sets "a".{established,negotiating}_ike_sa #2
|
||||
+ - leaves "a".routing_sa set to #1
|
||||
+ Child:
|
||||
+ - creates Child SA #3
|
||||
+ - connswitches Child SA #3 to "b"
|
||||
+ - establishes Child SA #3
|
||||
+ - sets "b".{routing,negotiating,established}_child_sa to #3
|
||||
+
|
||||
+- WEST retransmits "a":IKE_SA_INIT #1 to EAST
|
||||
+ - sees .established_ike_sa(?) is #2 stops negotiation
|
||||
+ "tun-out-1" #1: suppressing retransmit because IKE SA was superseded #2; drop this negotiation
|
||||
+ - tries to revive:
|
||||
+ EXPECTATION FAILED: "a" #1: revival: skipping, .negotiating_ike_sa #2 is is not us
|
||||
+
|
||||
+ref github #1989
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt
|
||||
new file mode 100644
|
||||
index 0000000000..d386cabf02
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/east.console.txt
|
||||
@@ -0,0 +1,74 @@
|
||||
+/testing/guestbin/swan-prep --nokey
|
||||
+Creating empty NSS database
|
||||
+east #
|
||||
+ ../../guestbin/ifconfig.sh eth0 add 192.0.20.254/24
|
||||
+ inet 192.0.20.254/24 scope global eth0
|
||||
+east #
|
||||
+ ipsec start
|
||||
+Redirecting to: [initsystem]
|
||||
+east #
|
||||
+ ../../guestbin/wait-until-pluto-started
|
||||
+east #
|
||||
+ ipsec whack --impair suppress_retransmits
|
||||
+east #
|
||||
+ ipsec add a
|
||||
+"a": added IKEv2 connection
|
||||
+east #
|
||||
+ ipsec add b
|
||||
+"b": added IKEv2 connection
|
||||
+east #
|
||||
+ # Initiate "b" from EAST.
|
||||
+east #
|
||||
+ #
|
||||
+east #
|
||||
+ # On WEST this is will match and establish connection "a" with IKE SA
|
||||
+east #
|
||||
+ # #2, and then switch to connection "b" for Child SA #3.
|
||||
+east #
|
||||
+ ipsec up b
|
||||
+"b" #1: initiating IKEv2 connection to 192.1.2.45 using UDP
|
||||
+"b" #1: sent IKE_SA_INIT request to 192.1.2.45:UDP/500
|
||||
+"b" #1: processed IKE_SA_INIT response from 192.1.2.45:UDP/500 {cipher=AES_GCM_16_256 integ=n/a prf=HMAC_SHA2_512 group=DH19}, initiating IKE_AUTH
|
||||
+"b" #1: sent IKE_AUTH request to 192.1.2.45:UDP/500
|
||||
+"b" #1: initiator established IKE SA; authenticated peer using authby=secret and ID_FQDN '@west'
|
||||
+"b" #2: initiator established Child SA using #1; IPsec tunnel [192.0.20.0/24===192.0.3.0/24] {ESP/ESN=>0xESPESP <0xESPESP xfrm=AES_GCM_16_256-NONE DPD=passive}
|
||||
+east #
|
||||
+ # non-zero counts confirm encrypted traffic flowing
|
||||
+east #
|
||||
+ ipsec trafficstatus
|
||||
+#2: "b", type=ESP, add_time=1234567890, inBytes=0, outBytes=0, maxBytes=2^63B, id='@west'
|
||||
+east #
|
||||
+ # do things line up?
|
||||
+east #
|
||||
+ ../../guestbin/ipsec-kernel-state.sh
|
||||
+src 192.1.2.23 dst 192.1.2.45
|
||||
+ proto esp spi 0xSPISPI reqid REQID mode tunnel
|
||||
+ replay-window 0 flag af-unspec esn
|
||||
+ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128
|
||||
+ anti-replay esn context:
|
||||
+ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX
|
||||
+ replay_window 0, bitmap-length 0
|
||||
+src 192.1.2.45 dst 192.1.2.23
|
||||
+ proto esp spi 0xSPISPI reqid REQID mode tunnel
|
||||
+ replay-window 0 flag af-unspec esn
|
||||
+ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128
|
||||
+ anti-replay esn context:
|
||||
+ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX
|
||||
+ replay_window 128, bitmap-length 4
|
||||
+ 00000000 00000000 00000000 XXXXXXXX
|
||||
+east #
|
||||
+ ../../guestbin/ipsec-kernel-policy.sh
|
||||
+src 192.0.3.0/24 dst 192.0.20.0/24
|
||||
+ dir fwd priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.45 dst 192.1.2.23
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+src 192.0.3.0/24 dst 192.0.20.0/24
|
||||
+ dir in priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.45 dst 192.1.2.23
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+src 192.0.20.0/24 dst 192.0.3.0/24
|
||||
+ dir out priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.23 dst 192.1.2.45
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+east #
|
||||
+
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh
|
||||
new file mode 100755
|
||||
index 0000000000..c84a482b6a
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/final.sh
|
||||
@@ -0,0 +1,6 @@
|
||||
+# non-zero counts confirm encrypted traffic flowing
|
||||
+ipsec trafficstatus
|
||||
+
|
||||
+# do things line up?
|
||||
+../../guestbin/ipsec-kernel-state.sh
|
||||
+../../guestbin/ipsec-kernel-policy.sh
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf
|
||||
new file mode 100644
|
||||
index 0000000000..cb3d584bc2
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.conf
|
||||
@@ -0,0 +1,32 @@
|
||||
+config setup
|
||||
+ logfile=/tmp/pluto.log
|
||||
+ logtime=no
|
||||
+ logappend=no
|
||||
+ dumpdir=/var/tmp
|
||||
+ plutodebug=all
|
||||
+ nhelpers=0
|
||||
+
|
||||
+conn base
|
||||
+ keyexchange=ikev2
|
||||
+ auto=ignore
|
||||
+ # host
|
||||
+ left=192.1.2.45
|
||||
+ right=192.1.2.23
|
||||
+ # auth
|
||||
+ leftid=@west
|
||||
+ rightid=@east
|
||||
+ authby=secret
|
||||
+ leftsubnet=192.0.3.0/24
|
||||
+ retransmit-timeout=10s
|
||||
+
|
||||
+conn a
|
||||
+ also=base
|
||||
+ # client
|
||||
+ leftsourceip=192.0.3.253
|
||||
+ rightsubnet=192.0.2.0/24
|
||||
+
|
||||
+conn b
|
||||
+ also=base
|
||||
+ # client
|
||||
+ leftsourceip=192.0.3.254
|
||||
+ rightsubnet=192.0.20.0/24
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets
|
||||
new file mode 100644
|
||||
index 0000000000..d3ed5698d0
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/ipsec.secrets
|
||||
@@ -0,0 +1 @@
|
||||
+@west @east : PSK "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
||||
diff --git a/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt
|
||||
new file mode 100644
|
||||
index 0000000000..00c98494e5
|
||||
--- /dev/null
|
||||
+++ b/testing/pluto/crossing-streams-23-conswitch-ike-sa-init-ikev2/west.console.txt
|
||||
@@ -0,0 +1,101 @@
|
||||
+/testing/guestbin/swan-prep --nokey
|
||||
+Creating empty NSS database
|
||||
+west #
|
||||
+ ipsec start
|
||||
+Redirecting to: [initsystem]
|
||||
+west #
|
||||
+ ../../guestbin/wait-until-pluto-started
|
||||
+west #
|
||||
+ ipsec whack --impair suppress_retransmits
|
||||
+west #
|
||||
+ # note order
|
||||
+west #
|
||||
+ ipsec add a
|
||||
+"a": added IKEv2 connection
|
||||
+west #
|
||||
+ ipsec add b
|
||||
+"b": added IKEv2 connection
|
||||
+west #
|
||||
+ # Initiate "a" with all packets blocked.
|
||||
+west #
|
||||
+ #
|
||||
+west #
|
||||
+ # This will create the negotiating IKE SA #1, and then hang.
|
||||
+west #
|
||||
+ ipsec whack --impair block_outbound:yes
|
||||
+IMPAIR: recording all outbound messages
|
||||
+IMPAIR: block all outbound messages: no -> yes
|
||||
+west #
|
||||
+ ipsec up a --asynchronous
|
||||
+"a" #1: initiating IKEv2 connection to 192.1.2.23 using UDP
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '"a" #1: IMPAIR: blocking outbound message 1'
|
||||
+"a" #1: IMPAIR: blocking outbound message 1
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '"a" #1: sent IKE_SA_INIT request'
|
||||
+"a" #1: sent IKE_SA_INIT request to 192.1.2.23:UDP/500
|
||||
+west #
|
||||
+ # With connection "a"'s IKE SA #1 stuck, unblock so that the peer's
|
||||
+west #
|
||||
+ # IKE SA #2, which will cross "a", can establish
|
||||
+west #
|
||||
+ ipsec whack --impair block_outbound:no
|
||||
+IMPAIR: block all outbound messages: yes -> no
|
||||
+west #
|
||||
+ # confirm that the peer's IKE SA established "a", and then the peer's
|
||||
+west #
|
||||
+ # Child SA needed to switch to "b" before establishing.
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '"a" #2: responder established IKE SA'
|
||||
+"a" #2: responder established IKE SA; authenticated peer using authby=secret and ID_FQDN '@east'
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '"a" #3: switched to "b"'
|
||||
+"a" #3: switched to "b"
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '"b" #3: responder established Child SA using #2'
|
||||
+"b" #3: responder established Child SA using #2; IPsec tunnel [192.0.3.0/24===192.0.20.0/24] {ESP/ESN=>0xESPESP <0xESPESP xfrm=AES_GCM_16_256-NONE DPD=passive}
|
||||
+west #
|
||||
+ # this is where pluto realises that the stream crossed
|
||||
+west #
|
||||
+ ../../guestbin/wait-for-pluto.sh --match '#1: dropping negotiation'
|
||||
+"a" #1: dropping negotiation as superseeded by established IKE SA #2
|
||||
+west #
|
||||
+ # non-zero counts confirm encrypted traffic flowing
|
||||
+west #
|
||||
+ ipsec trafficstatus
|
||||
+#3: "b", type=ESP, add_time=1234567890, inBytes=0, outBytes=0, maxBytes=2^63B, id='@east'
|
||||
+west #
|
||||
+ # do things line up?
|
||||
+west #
|
||||
+ ../../guestbin/ipsec-kernel-state.sh
|
||||
+src 192.1.2.45 dst 192.1.2.23
|
||||
+ proto esp spi 0xSPISPI reqid REQID mode tunnel
|
||||
+ replay-window 0 flag af-unspec esn
|
||||
+ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128
|
||||
+ anti-replay esn context:
|
||||
+ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX
|
||||
+ replay_window 0, bitmap-length 0
|
||||
+src 192.1.2.23 dst 192.1.2.45
|
||||
+ proto esp spi 0xSPISPI reqid REQID mode tunnel
|
||||
+ replay-window 0 flag af-unspec esn
|
||||
+ aead rfc4106(gcm(aes)) 0xENCAUTHKEY 128
|
||||
+ anti-replay esn context:
|
||||
+ seq-hi 0x0, seq 0xXX, oseq-hi 0x0, oseq 0xXX
|
||||
+ replay_window 128, bitmap-length 4
|
||||
+ 00000000 00000000 00000000 XXXXXXXX
|
||||
+west #
|
||||
+ ../../guestbin/ipsec-kernel-policy.sh
|
||||
+src 192.0.3.0/24 dst 192.0.20.0/24
|
||||
+ dir out priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.45 dst 192.1.2.23
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+src 192.0.20.0/24 dst 192.0.3.0/24
|
||||
+ dir fwd priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.23 dst 192.1.2.45
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+src 192.0.20.0/24 dst 192.0.3.0/24
|
||||
+ dir in priority PRIORITY ptype main
|
||||
+ tmpl src 192.1.2.23 dst 192.1.2.45
|
||||
+ proto esp reqid REQID mode tunnel
|
||||
+west #
|
||||
+
|
||||
--
|
||||
2.48.1
|
||||
|
||||
|
||||
From ee7a62dc7f400f4b830e64e0385a6d16fda234b3 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cagney <cagney@gnu.org>
|
||||
Date: Mon, 6 Jan 2025 15:38:03 -0500
|
||||
Subject: [PATCH 4/4] ikev2: in event_v2_retransmit() check .established_ike_sa
|
||||
!= SOS_NOBODY
|
||||
|
||||
That is:
|
||||
!IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa != SOS_NOBODY
|
||||
when the streams cross, the etablished IKE SA may be older.
|
||||
---
|
||||
programs/pluto/ikev2_retransmit.c | 32 ++++++++++++++++++++-----------
|
||||
1 file changed, 21 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/programs/pluto/ikev2_retransmit.c b/programs/pluto/ikev2_retransmit.c
|
||||
index df6ab99e63..7b0197445c 100644
|
||||
--- a/programs/pluto/ikev2_retransmit.c
|
||||
+++ b/programs/pluto/ikev2_retransmit.c
|
||||
@@ -49,25 +49,35 @@ void event_v2_retransmit(struct state *ike_sa, monotime_t now UNUSED)
|
||||
return;
|
||||
}
|
||||
|
||||
- /* if this connection has a newer Child SA than this state
|
||||
- * this negotiation is not relevant any more. would this
|
||||
- * cover if there are multiple CREATE_CHILD_SA pending on this
|
||||
- * IKE negotiation ???
|
||||
- *
|
||||
+ /*
|
||||
* XXX: Suspect this is to handle a race where the other end
|
||||
* brings up the connection first? For that case, shouldn't
|
||||
* this state have been deleted?
|
||||
*
|
||||
- * NOTE: a larger serialno does not mean superseded. crossed
|
||||
+ * NOTE: a larger serialno does not mean superseded. Crossed
|
||||
* streams could mean the lower serial established later and
|
||||
- * is the "newest". Should > be replaced with != ?
|
||||
+ * is the "newest". Hence the equality check (and not >).
|
||||
*/
|
||||
|
||||
struct connection *c = ike->sa.st_connection;
|
||||
- if (!IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa > ike->sa.st_serialno) {
|
||||
- llog_sa(RC_LOG, ike,
|
||||
- "suppressing retransmit because IKE SA was superseded #%lu; drop this negotiation",
|
||||
- c->established_ike_sa);
|
||||
+ if (!IS_IKE_SA_ESTABLISHED(&ike->sa) && c->established_ike_sa != SOS_NOBODY) {
|
||||
+ /*
|
||||
+ * The connection is established, yet this IKE SA is
|
||||
+ * not. Presumably this means that the peer also
|
||||
+ * initiated and established an IKE SA leaving this
|
||||
+ * IKE SA in limbo.
|
||||
+ *
|
||||
+ * Note: since it isn't established it can't be the
|
||||
+ * connection's established IKE SA.
|
||||
+ *
|
||||
+ * Note: this may also leave the Child SA for the
|
||||
+ * connection in limbo. Hopefully revival code will
|
||||
+ * pick that up.
|
||||
+ */
|
||||
+ PEXPECT(ike->sa.logger, c->established_ike_sa != ike->sa.st_serialno);
|
||||
+ llog(RC_LOG, ike->sa.logger,
|
||||
+ "suppressing retransmit because IKE SA was superseded by #%lu; drop this negotiation",
|
||||
+ c->established_ike_sa);
|
||||
pstat_sa_failed(&ike->sa, REASON_SUPERSEDED_BY_NEW_SA);
|
||||
connection_delete_ike_family(&ike, HERE);
|
||||
return;
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -47,6 +47,7 @@ Source5: https://download.libreswan.org/cavs/ikev2.fax.bz2
|
||||
Patch1: libreswan-4.15-ipsec_import.patch
|
||||
Patch2: libreswan-5.1-rereadsecrets.patch
|
||||
Patch3: libreswan-5.1-opt-protoport.patch
|
||||
Patch4: libreswan-5.1-pexpect-negotiating-ike-sa.patch
|
||||
|
||||
BuildRequires: audit-libs-devel
|
||||
BuildRequires: bison
|
||||
|
||||
Loading…
Reference in New Issue
Block a user