aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-04-10 11:31:17 +0200
committerMartin Willi <martin@revosec.ch>2014-04-17 09:59:06 +0200
commit0b3bea39653f4d93bcff4011f3e255cd82400390 (patch)
treeffa4a5a71ec48af3c419ed2fdbc86b2e898043ae
parentf02cabbe358cc2f5636de0f7de7be114884302c3 (diff)
downloadstrongswan-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.c49
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;
}