aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-04-17 10:14:49 +0200
committerMartin Willi <martin@revosec.ch>2014-04-17 10:14:49 +0200
commit95083fc6fb6ad13b9055f3df594e7f5ba77332dc (patch)
treeffa4a5a71ec48af3c419ed2fdbc86b2e898043ae
parent094963d1b16024c56adc624cc97729ce424e2814 (diff)
parent0b3bea39653f4d93bcff4011f3e255cd82400390 (diff)
downloadstrongswan-95083fc6fb6ad13b9055f3df594e7f5ba77332dc.tar.bz2
strongswan-95083fc6fb6ad13b9055f3df594e7f5ba77332dc.tar.xz
Merge branch 'reauth-collision'
Fixes two collisions between IKE_SA re-authentication and CHILD_SA rekeying.
-rw-r--r--src/libcharon/processing/jobs/rekey_ike_sa_job.c49
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c6
2 files changed, 53 insertions, 2 deletions
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
index 712c7c2c1..516dc5dd5 100644
--- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
@@ -46,11 +46,47 @@ METHOD(job_t, destroy, void,
free(this);
}
+/**
+ * Check if we should delay a reauth, and by how many seconds
+ */
+static u_int32_t get_retry_delay(ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ child_sa_t *child_sa;
+ u_int32_t retry = 0;
+
+ /* avoid reauth collisions for certain IKE_SA/CHILD_SA states */
+ if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
+ {
+ retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+ DBG1(DBG_IKE, "unable to reauthenticate in %N state, delaying for %us",
+ ike_sa_state_names, ike_sa->get_state(ike_sa), retry);
+ }
+ else
+ {
+ enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (enumerator->enumerate(enumerator, &child_sa))
+ {
+ if (child_sa->get_state(child_sa) != CHILD_INSTALLED)
+ {
+ retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+ DBG1(DBG_IKE, "unable to reauthenticate in CHILD_SA %N state, "
+ "delaying for %us", child_sa_state_names,
+ child_sa->get_state(child_sa), retry);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return retry;
+}
+
METHOD(job_t, execute, job_requeue_t,
private_rekey_ike_sa_job_t *this)
{
ike_sa_t *ike_sa;
status_t status = SUCCESS;
+ u_int32_t retry = 0;
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
this->ike_sa_id);
@@ -62,7 +98,11 @@ METHOD(job_t, execute, job_requeue_t,
{
if (this->reauth)
{
- status = ike_sa->reauth(ike_sa);
+ retry = get_retry_delay(ike_sa);
+ if (!retry)
+ {
+ status = ike_sa->reauth(ike_sa);
+ }
}
else
{
@@ -71,13 +111,18 @@ METHOD(job_t, execute, job_requeue_t,
if (status == DESTROY_ME)
{
- charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
}
else
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
}
+ if (retry)
+ {
+ return JOB_RESCHEDULE(retry);
+ }
return JOB_REQUEUE_NONE;
}
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index e0ade07b2..35b7e12c9 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -1192,6 +1192,12 @@ METHOD(task_t, build_r, status_t,
message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
return SUCCESS;
}
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
+ {
+ DBG1(DBG_IKE, "unable to create CHILD_SA while deleting IKE_SA");
+ message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
+ return SUCCESS;
+ }
if (this->config == NULL)
{