From: Martin Willi Date: Thu, 10 Apr 2014 09:31:17 +0000 (+0200) Subject: ike: Delay actively initiated reauthentication when other exchanges in progress X-Git-Tag: 5.2.0dr2~31^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b3bea39653f4d93bcff4011f3e255cd82400390;p=thirdparty%2Fstrongswan.git 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. --- diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c index 712c7c2c15..516dc5dd5c 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; }