Commit 1f9abe01d7 for strongswan.org
commit 1f9abe01d7737aec64aeed378e4975c94d8448c2
Author: Tobias Brunner <tobias@strongswan.org>
Date: Fri Jun 5 13:50:55 2026 +0200
ikev2: Respond with STATE_NOT_FOUND if IKE_FOLLOWUP_KE arrives outside of a rekeying
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 5a19ce85b3..b2aab6f8d6 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1121,6 +1121,44 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
return SUCCESS;
}
+/**
+ * Send a notify back to the sender
+ */
+static void send_notify_response(private_task_manager_t *this,
+ message_t *request, notify_type_t type,
+ chunk_t data)
+{
+ message_t *response;
+ packet_t *packet;
+ host_t *me, *other;
+
+ response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
+ response->set_exchange_type(response, request->get_exchange_type(request));
+ response->set_request(response, FALSE);
+ response->set_message_id(response, request->get_message_id(request));
+ response->add_notify(response, FALSE, type, data);
+ me = this->ike_sa->get_my_host(this->ike_sa);
+ if (me->is_anyaddr(me))
+ {
+ me = request->get_destination(request);
+ this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
+ }
+ other = this->ike_sa->get_other_host(this->ike_sa);
+ if (other->is_anyaddr(other))
+ {
+ other = request->get_source(request);
+ this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
+ }
+ response->set_source(response, me->clone(me));
+ response->set_destination(response, other->clone(other));
+ if (this->ike_sa->generate_message(this->ike_sa, response,
+ &packet) == SUCCESS)
+ {
+ charon->sender->send(charon->sender, packet);
+ }
+ response->destroy(response);
+}
+
/**
* handle an incoming request message
*/
@@ -1233,6 +1271,21 @@ static status_t process_request(private_task_manager_t *this,
array_insert(this->passive_tasks, ARRAY_TAIL, task);
break;
}
+ case IKE_FOLLOWUP_KE:
+ {
+ if (state == IKE_CREATED ||
+ state == IKE_CONNECTING)
+ {
+ DBG1(DBG_IKE, "received IKE_FOLLOWUP_KE request for "
+ "unestablished IKE_SA, rejected");
+ return FAILED;
+ }
+ /* receiving this when we don't have an active rekey task is
+ * an error, we send back a notify accordingly */
+ send_notify_response(this, message, STATE_NOT_FOUND,
+ chunk_empty);
+ return SUCCESS;
+ }
case INFORMATIONAL:
{
enumerator = message->create_payload_enumerator(message);
@@ -1524,44 +1577,6 @@ static status_t handle_fragment(private_task_manager_t *this,
return status;
}
-/**
- * Send a notify back to the sender
- */
-static void send_notify_response(private_task_manager_t *this,
- message_t *request, notify_type_t type,
- chunk_t data)
-{
- message_t *response;
- packet_t *packet;
- host_t *me, *other;
-
- response = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
- response->set_exchange_type(response, request->get_exchange_type(request));
- response->set_request(response, FALSE);
- response->set_message_id(response, request->get_message_id(request));
- response->add_notify(response, FALSE, type, data);
- me = this->ike_sa->get_my_host(this->ike_sa);
- if (me->is_anyaddr(me))
- {
- me = request->get_destination(request);
- this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
- }
- other = this->ike_sa->get_other_host(this->ike_sa);
- if (other->is_anyaddr(other))
- {
- other = request->get_source(request);
- this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
- }
- response->set_source(response, me->clone(me));
- response->set_destination(response, other->clone(other));
- if (this->ike_sa->generate_message(this->ike_sa, response,
- &packet) == SUCCESS)
- {
- charon->sender->send(charon->sender, packet);
- }
- response->destroy(response);
-}
-
/**
* Send an INVALID_SYNTAX notify and destroy the IKE_SA for authenticated
* messages.
diff --git a/src/libcharon/tests/suites/test_child_rekey.c b/src/libcharon/tests/suites/test_child_rekey.c
index 4ef081a249..7305782538 100644
--- a/src/libcharon/tests/suites/test_child_rekey.c
+++ b/src/libcharon/tests/suites/test_child_rekey.c
@@ -2669,6 +2669,7 @@ START_TEST(test_collision_delayed_response_multi_ke_failure)
/* IKE_FOLLOWUP_KE { KEi, N(ADD_KE) } --> */
assert_payload(IN, PLV2_KEY_EXCHANGE);
assert_notify(IN, ADDITIONAL_KEY_EXCHANGE);
+ assert_single_notify(OUT, STATE_NOT_FOUND);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
/* child_rekey/child_updown */
diff --git a/src/libcharon/tests/suites/test_ike_rekey.c b/src/libcharon/tests/suites/test_ike_rekey.c
index 2c4102201d..0ce3dd0662 100644
--- a/src/libcharon/tests/suites/test_ike_rekey.c
+++ b/src/libcharon/tests/suites/test_ike_rekey.c
@@ -1918,6 +1918,7 @@ START_TEST(test_collision_delayed_response_multi_ke_failure)
/* IKE_FOLLOWUP_KE { KEi, N(ADD_KE) } --> */
assert_payload(IN, PLV2_KEY_EXCHANGE);
assert_notify(IN, ADDITIONAL_KEY_EXCHANGE);
+ assert_single_notify(OUT, STATE_NOT_FOUND);
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
/* ike_updown/rekey/child_updown */