child-rekey: Prevent crash if peer rekeys a Child SA twice before sending a delete

Some (Windows) peers have been seen to initiate a second rekeying for the
same Child SA.  Presumably, this happens if a rekey request from us for
the same old Child SA arrives while it waits for the response to its
first rekey request.  Once we receive the delete for the old SA, we
conclude the rekeying with the second replacement.  However, the first
replacement remained linked to the old SA.  So this change prevents a
crash once the peer sends a delete for that first replacement (which it
seems to do after about 5 minutes).

References strongswan/strongswan#2944
Closes strongswan/strongswan#2945
This commit is contained in:
Tobias Brunner
2025-12-10 17:10:29 +01:00
parent 96468d2891
commit 84a5208d98
+8 -1
View File
@@ -400,7 +400,7 @@ METHOD(task_t, build_r, status_t,
{
notify_payload_t *notify;
child_cfg_t *config;
child_sa_t *child_sa;
child_sa_t *child_sa, *old_replacement;
child_sa_state_t state = CHILD_INSTALLED;
uint32_t reqid;
bool followup_sent = FALSE;
@@ -470,6 +470,13 @@ METHOD(task_t, build_r, status_t,
if (child_sa && child_sa->get_state(child_sa) == CHILD_INSTALLED)
{
this->child_sa->set_state(this->child_sa, CHILD_REKEYED);
/* we've seen peers sending multiple rekey requests (probably a bug in
* their collision handling), so make sure we unlink any previous SA */
old_replacement = this->child_sa->get_rekey_sa(this->child_sa);
if (old_replacement)
{
old_replacement->set_rekey_sa(old_replacement, NULL);
}
/* link the SAs to handle possible collisions */
this->child_sa->set_rekey_sa(this->child_sa, child_sa);
child_sa->set_rekey_sa(child_sa, this->child_sa);