child-create: Update CHILD_SA IP addresses before installation

We create the child_sa_t object when initiating the CREATE_CHILD_SA
request, however, the IP addresses/ports might have changed once we
eventually receive the response (potentially to a retransmit sent to
a different address).  So update them before installing the SA and
policies.

If the local address changed too and depending on the kernel
implementation, the temporary SA created to allocate the inbound SPI
might remain as it can't be updated.  This could cause issues if e.g.
the address switches back before that SA expired (the updated inbound
SA conflicts with the temporary one), or if that happens close together
and the expire (having to wait for the address update) causes the
updated SA to get deleted.

Fixes #3164.
This commit is contained in:
Tobias Brunner
2020-10-27 16:45:10 +01:00
parent 9118fd39d7
commit bce0c5fd74
+11 -6
View File
@@ -707,6 +707,17 @@ static status_t select_and_install(private_child_create_t *this,
}
}
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
this->child_sa->set_mode(this->child_sa, this->mode);
this->child_sa->set_protocol(this->child_sa,
this->proposal->get_protocol(this->proposal));
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
/* addresses might have changed since we originally sent the request, update
* them before we configure any policies and install the SAs */
this->child_sa->update(this->child_sa, me, other, NULL,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
this->child_sa->set_policies(this->child_sa, my_ts, other_ts);
if (!this->initiator)
{
@@ -716,12 +727,6 @@ static status_t select_and_install(private_child_create_t *this,
offsetof(traffic_selector_t, destroy));
}
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
this->child_sa->set_mode(this->child_sa, this->mode);
this->child_sa->set_protocol(this->child_sa,
this->proposal->get_protocol(this->proposal));
if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
{
this->my_cpi = this->other_cpi = 0;