diff options
author | Martin Willi <martin@revosec.ch> | 2014-04-17 10:14:49 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-04-17 10:14:49 +0200 |
commit | 95083fc6fb6ad13b9055f3df594e7f5ba77332dc (patch) | |
tree | ffa4a5a71ec48af3c419ed2fdbc86b2e898043ae | |
parent | 094963d1b16024c56adc624cc97729ce424e2814 (diff) | |
parent | 0b3bea39653f4d93bcff4011f3e255cd82400390 (diff) | |
download | strongswan-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.c | 49 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 6 |
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) { |