ikev2: Trigger make-before-break reauthentication instead of reauth task

This commit is contained in:
Martin Willi
2015-02-20 13:34:57 +01:00
parent c8e7dbcb56
commit 349f7f2412
3 changed files with 89 additions and 2 deletions
+10
View File
@@ -196,6 +196,16 @@ charon.load_modular = no
charon.max_packet = 10000
Maximum packet size accepted by charon.
charon.make_before_break = no
Initiate IKEv2 reauthentication with a make-before-break scheme.
Initiate IKEv2 reauthentication with a make-before-break instead of a
break-before-make scheme. Make-before-break uses overlapping IKE and
CHILD_SA during reauthentication by first recreating all new SAs before
deleting the old ones. This behavior can be beneficial to avoid connectivity
gaps during reauthentication, but requires support for overlapping SAs by
the peer. strongSwan can handle such overlapping SAs since version 5.3.0.
charon.mem-pool.reassign_online = no
Reassign an online IP address lease from an in-memory address pool if a
client with the same identity requests it explicitly.
+3 -2
View File
@@ -936,8 +936,9 @@ struct ike_sa_t {
/**
* Reauthenticate the IKE_SA.
*
* Create a completely new IKE_SA with authentication, recreates all children
* within the IKE_SA, closes this IKE_SA.
* Triggers a new IKE_SA that replaces this one. IKEv1 implicitly inherits
* all Quick Modes, while IKEv2 recreates all active and queued CHILD_SAs
* in the new IKE_SA.
*
* @return DESTROY_ME to destroy the IKE_SA
*/
+76
View File
@@ -171,6 +171,11 @@ struct private_task_manager_t {
* Base to calculate retransmission timeout
*/
double retransmit_base;
/**
* Use make-before-break instead of break-before-make reauth?
*/
bool make_before_break;
};
/**
@@ -1505,9 +1510,78 @@ METHOD(task_manager_t, queue_ike_rekey, void,
queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE));
}
/**
* Start reauthentication using make-before-break
*/
static void trigger_mbb_reauth(private_task_manager_t *this)
{
enumerator_t *enumerator;
child_sa_t *child_sa;
child_cfg_t *cfg;
ike_sa_t *new;
host_t *host;
task_t *task;
new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
this->ike_sa->get_version(this->ike_sa), TRUE);
if (!new)
{ /* shouldn't happen */
return;
}
new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
host = this->ike_sa->get_other_host(this->ike_sa);
new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa);
new->set_my_host(new, host->clone(host));
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
while (enumerator->enumerate(enumerator, &host))
{
new->add_virtual_ip(new, TRUE, host);
}
enumerator->destroy(enumerator);
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, &child_sa))
{
cfg = child_sa->get_config(child_sa);
new->queue_task(new, &child_create_create(new, cfg->get_ref(cfg),
FALSE, NULL, NULL)->task);
}
enumerator->destroy(enumerator);
enumerator = array_create_enumerator(this->queued_tasks);
while (enumerator->enumerate(enumerator, &task))
{
if (task->get_type(task) == TASK_CHILD_CREATE)
{
task->migrate(task, new);
new->queue_task(new, task);
array_remove_at(this->queued_tasks, enumerator);
}
}
enumerator->destroy(enumerator);
if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME)
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
}
else
{
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
DBG1(DBG_IKE, "reauthenticating IKE_SA failed");
}
charon->bus->set_sa(charon->bus, this->ike_sa);
}
METHOD(task_manager_t, queue_ike_reauth, void,
private_task_manager_t *this)
{
if (this->make_before_break)
{
return trigger_mbb_reauth(this);
}
queue_task(this, (task_t*)ike_reauth_create(this->ike_sa));
}
@@ -1773,6 +1847,8 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
"%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns),
.retransmit_base = lib->settings->get_double(lib->settings,
"%s.retransmit_base", RETRANSMIT_BASE, lib->ns),
.make_before_break = lib->settings->get_bool(lib->settings,
"%s.make_before_break", FALSE, lib->ns),
);
return &this->public;