ike-sa: Add option to force the destruction of an IKE_SA after initiating a delete
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user