diff options
author | Martin Willi <martin@revosec.ch> | 2014-04-10 11:31:17 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-04-17 09:59:06 +0200 |
commit | 0b3bea39653f4d93bcff4011f3e255cd82400390 (patch) | |
tree | ffa4a5a71ec48af3c419ed2fdbc86b2e898043ae | |
parent | f02cabbe358cc2f5636de0f7de7be114884302c3 (diff) | |
download | strongswan-0b3bea39653f4d93bcff4011f3e255cd82400390.tar.bz2 strongswan-0b3bea39653f4d93bcff4011f3e255cd82400390.tar.xz |
ike: Delay actively initiated reauthentication when other exchanges in progress
If any other IKE or CHILD_SA operation takes places, we should not start
initiating reauthentication to avoid any potential races.
-rw-r--r-- | src/libcharon/processing/jobs/rekey_ike_sa_job.c | 49 |
1 files changed, 47 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; } |