From: Tobias Brunner Date: Thu, 2 Jun 2016 13:13:24 +0000 (+0200) Subject: ike-rekey: Return TEMPORARY_FAILURE when concurrently creating a CHILD_SA X-Git-Tag: 5.5.0dr1~4^2~9 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=2045cadc1cdb5e290ab1deb63d884da0f321a0e6;p=thirdparty%2Fstrongswan.git ike-rekey: Return TEMPORARY_FAILURE when concurrently creating a CHILD_SA --- diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c index 44684bca6b..2f0552a335 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c @@ -182,38 +182,59 @@ METHOD(task_t, build_i, status_t, return NEED_MORE; } -METHOD(task_t, process_r, status_t, - private_ike_rekey_t *this, message_t *message) +/** + * Check if there are any half-open children + */ +static bool have_half_open_children(private_ike_rekey_t *this) { enumerator_t *enumerator; child_sa_t *child_sa; - - if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING) - { - DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting"); - this->failed_temporarily = TRUE; - return NEED_MORE; - } + task_t *task; enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { switch (child_sa->get_state(child_sa)) { - case CHILD_CREATED: case CHILD_REKEYING: case CHILD_RETRYING: case CHILD_DELETING: - /* we do not allow rekeying while we have children in-progress */ - DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open"); enumerator->destroy(enumerator); - this->failed_temporarily = TRUE; - return NEED_MORE; + return TRUE; default: break; } } enumerator->destroy(enumerator); + enumerator = this->ike_sa->create_task_enumerator(this->ike_sa, + TASK_QUEUE_ACTIVE); + while (enumerator->enumerate(enumerator, (void**)&task)) + { + if (task->get_type(task) == TASK_CHILD_CREATE) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +METHOD(task_t, process_r, status_t, + private_ike_rekey_t *this, message_t *message) +{ + if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING) + { + DBG1(DBG_IKE, "peer initiated rekeying, but we are deleting"); + this->failed_temporarily = TRUE; + return NEED_MORE; + } + if (have_half_open_children(this)) + { + DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open"); + this->failed_temporarily = TRUE; + return NEED_MORE; + } this->new_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, this->ike_sa->get_version(this->ike_sa), FALSE);