From: Tobias Brunner Date: Fri, 27 Apr 2018 15:27:53 +0000 (+0200) Subject: ike-sa: Add option to force the destruction of an IKE_SA after initiating a delete X-Git-Tag: 5.6.3dr2~2^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a79d5103544295ed83c38448f104e3726aaa5469;p=thirdparty%2Fstrongswan.git ike-sa: Add option to force the destruction of an IKE_SA after initiating a delete --- diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index dd8255f413..6a37fff455 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -557,7 +557,7 @@ METHOD(job_t, terminate_ike_execute, job_requeue_t, listener->ike_sa = ike_sa; listener->lock->unlock(listener->lock); - if (ike_sa->delete(ike_sa) != DESTROY_ME) + if (ike_sa->delete(ike_sa, FALSE) != DESTROY_ME) { /* delete failed */ listener->status = FAILED; charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c index 53a1705108..d539e4b940 100644 --- a/src/libcharon/processing/jobs/delete_ike_sa_job.c +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c @@ -64,7 +64,7 @@ METHOD(job_t, execute, job_requeue_t, } if (this->delete_if_established) { - if (ike_sa->delete(ike_sa) == DESTROY_ME) + if (ike_sa->delete(ike_sa, FALSE) == DESTROY_ME) { charon->ike_sa_manager->checkin_and_destroy( charon->ike_sa_manager, ike_sa); diff --git a/src/libcharon/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c index bf16e51b52..e46861f095 100644 --- a/src/libcharon/processing/jobs/inactivity_job.c +++ b/src/libcharon/processing/jobs/inactivity_job.c @@ -101,7 +101,7 @@ METHOD(job_t, execute, job_requeue_t, { DBG1(DBG_JOB, "deleting IKE_SA after %d seconds " "of CHILD_SA inactivity", this->timeout); - status = ike_sa->delete(ike_sa); + status = ike_sa->delete(ike_sa, FALSE); } else { diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 18d1c24410..f39fed6f06 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2017 Tobias Brunner + * Copyright (C) 2006-2018 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -1793,8 +1793,10 @@ METHOD(ike_sa_t, destroy_child_sa, status_t, } METHOD(ike_sa_t, delete_, status_t, - private_ike_sa_t *this) + private_ike_sa_t *this, bool force) { + status_t status = DESTROY_ME; + switch (this->state) { case IKE_ESTABLISHED: @@ -1806,19 +1808,38 @@ METHOD(ike_sa_t, delete_, status_t, charon->bus->alert(charon->bus, ALERT_IKE_SA_EXPIRED); } this->task_manager->queue_ike_delete(this->task_manager); - return this->task_manager->initiate(this->task_manager); + status = this->task_manager->initiate(this->task_manager); + break; case IKE_CREATED: DBG1(DBG_IKE, "deleting unestablished IKE_SA"); break; case IKE_PASSIVE: break; default: - DBG1(DBG_IKE, "destroying IKE_SA in state %N " - "without notification", ike_sa_state_names, this->state); - charon->bus->ike_updown(charon->bus, &this->public, FALSE); + DBG1(DBG_IKE, "destroying IKE_SA in state %N without notification", + ike_sa_state_names, this->state); + force = TRUE; break; } - return DESTROY_ME; + + if (force) + { + status = DESTROY_ME; + + if (this->version == IKEV2) + { /* for IKEv1 we trigger this in the ISAKMP delete task */ + switch (this->state) + { + case IKE_ESTABLISHED: + case IKE_REKEYING: + case IKE_DELETING: + charon->bus->ike_updown(charon->bus, &this->public, FALSE); + default: + break; + } + } + } + return status; } METHOD(ike_sa_t, rekey, status_t, diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index b4fbc56d7c..316b713ee0 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2017 Tobias Brunner + * Copyright (C) 2006-2018 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -776,15 +776,18 @@ struct ike_sa_t { * * Sends a delete message to the remote peer and waits for * its response. If the response comes in, or a timeout occurs, - * the IKE SA gets deleted. + * the IKE SA gets destroyed, unless force is TRUE then the IKE_SA is + * destroyed immediately without waiting for a response. * + * @param force whether to immediately destroy the IKE_SA afterwards + * without waiting for a response * @return * - SUCCESS if deletion is initialized - * - DESTROY_ME, if the IKE_SA is not in - * an established state and can not be - * deleted (but destroyed). + * - DESTROY_ME, if destroying is forced, or the IKE_SA + * is not in an established state and can not be + * deleted (but destroyed) */ - status_t (*delete) (ike_sa_t *this); + status_t (*delete) (ike_sa_t *this, bool force); /** * Update IKE_SAs after network interfaces have changed. diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 101d986786..2a499db405 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -2021,7 +2021,7 @@ static status_t enforce_replace(private_ike_sa_manager_t *this, } DBG1(DBG_IKE, "deleting duplicate IKE_SA for peer '%Y' due to " "uniqueness policy", other); - return duplicate->delete(duplicate); + return duplicate->delete(duplicate, FALSE); } METHOD(ike_sa_manager_t, check_uniqueness, bool, @@ -2266,20 +2266,7 @@ METHOD(ike_sa_manager_t, flush, void, while (enumerator->enumerate(enumerator, &entry, &segment)) { charon->bus->set_sa(charon->bus, entry->ike_sa); - if (entry->ike_sa->get_version(entry->ike_sa) == IKEV2) - { /* as the delete never gets processed, fire down events */ - switch (entry->ike_sa->get_state(entry->ike_sa)) - { - case IKE_ESTABLISHED: - case IKE_REKEYING: - case IKE_DELETING: - charon->bus->ike_updown(charon->bus, entry->ike_sa, FALSE); - break; - default: - break; - } - } - entry->ike_sa->delete(entry->ike_sa); + entry->ike_sa->delete(entry->ike_sa, TRUE); } enumerator->destroy(enumerator); diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c index 2f0552a335..11123b4158 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c @@ -363,7 +363,7 @@ METHOD(task_t, process_i, status_t, /* IKE_SAs in state IKE_REKEYED are silently deleted, so we use * IKE_REKEYING */ this->new_sa->set_state(this->new_sa, IKE_REKEYING); - if (this->new_sa->delete(this->new_sa) == DESTROY_ME) + if (this->new_sa->delete(this->new_sa, FALSE) == DESTROY_ME) { this->new_sa->destroy(this->new_sa); } diff --git a/src/libcharon/tests/suites/test_child_delete.c b/src/libcharon/tests/suites/test_child_delete.c index 437e919c7a..8660d72914 100644 --- a/src/libcharon/tests/suites/test_child_delete.c +++ b/src/libcharon/tests/suites/test_child_delete.c @@ -290,7 +290,7 @@ START_TEST(test_collision_ike_delete) } call_ikesa(a, delete_child_sa, PROTO_ESP, spi_a, FALSE); assert_child_sa_state(a, spi_a, CHILD_DELETING); - call_ikesa(b, delete); + call_ikesa(b, delete, FALSE); assert_ike_sa_state(b, IKE_DELETING); /* RFC 7296, 2.25.2 does not explicitly state what the behavior SHOULD be if diff --git a/src/libcharon/tests/suites/test_child_rekey.c b/src/libcharon/tests/suites/test_child_rekey.c index 6bf3588a18..51d577cd80 100644 --- a/src/libcharon/tests/suites/test_child_rekey.c +++ b/src/libcharon/tests/suites/test_child_rekey.c @@ -1906,7 +1906,7 @@ START_TEST(test_collision_ike_delete) &a, &b, NULL); } initiate_rekey(a, spi_a); - call_ikesa(b, delete); + call_ikesa(b, delete, FALSE); assert_ike_sa_state(b, IKE_DELETING); /* this should never get called as there is no successful rekeying on diff --git a/src/libcharon/tests/suites/test_ike_delete.c b/src/libcharon/tests/suites/test_ike_delete.c index d79f9bc505..7633718d45 100644 --- a/src/libcharon/tests/suites/test_ike_delete.c +++ b/src/libcharon/tests/suites/test_ike_delete.c @@ -40,7 +40,7 @@ START_TEST(test_regular) } assert_hook_not_called(ike_updown); assert_hook_not_called(child_updown); - call_ikesa(a, delete); + call_ikesa(a, delete, FALSE); assert_ike_sa_state(a, IKE_DELETING); assert_hook(); assert_hook(); @@ -81,9 +81,9 @@ START_TEST(test_collision) assert_hook_not_called(ike_updown); assert_hook_not_called(child_updown); - call_ikesa(a, delete); + call_ikesa(a, delete, FALSE); assert_ike_sa_state(a, IKE_DELETING); - call_ikesa(b, delete); + call_ikesa(b, delete, FALSE); assert_ike_sa_state(b, IKE_DELETING); assert_hook(); assert_hook(); diff --git a/src/libcharon/tests/suites/test_ike_rekey.c b/src/libcharon/tests/suites/test_ike_rekey.c index e22a0c2883..b6a0154455 100644 --- a/src/libcharon/tests/suites/test_ike_rekey.c +++ b/src/libcharon/tests/suites/test_ike_rekey.c @@ -1319,7 +1319,7 @@ START_TEST(test_collision_delete) assert_hook_not_called(ike_rekey); initiate_rekey(a); - call_ikesa(b, delete); + call_ikesa(b, delete, FALSE); assert_ike_sa_state(b, IKE_DELETING); /* RFC 7296, 2.25.2: If a peer receives a request to rekey an IKE SA that @@ -1401,7 +1401,7 @@ START_TEST(test_collision_delete_drop_delete) assert_hook_not_called(ike_rekey); initiate_rekey(a); - call_ikesa(b, delete); + call_ikesa(b, delete, FALSE); assert_ike_sa_state(b, IKE_DELETING); /* RFC 7296, 2.25.2: If a peer receives a request to rekey an IKE SA that