diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2015-04-11 22:03:59 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2015-04-11 22:03:59 +0200 |
commit | 83b8aebb19fe6e49e13a05d4e8f5ab9a06177642 (patch) | |
tree | 51255545ba43b84aa5d673bd0eb557cbd0155c9e /src/libcharon/sa/ikev2/task_manager_v2.c | |
parent | 2b8de74ff4c334c25e89988c4a401b24b5bcf03d (diff) | |
download | vyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.tar.gz vyos-strongswan-83b8aebb19fe6e49e13a05d4e8f5ab9a06177642.zip |
Imported Upstream version 5.3.0
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 113 |
1 files changed, 98 insertions, 15 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index eb7df3516..298167703 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -29,6 +29,7 @@ #include <sa/ikev2/tasks/ike_cert_post.h> #include <sa/ikev2/tasks/ike_rekey.h> #include <sa/ikev2/tasks/ike_reauth.h> +#include <sa/ikev2/tasks/ike_reauth_complete.h> #include <sa/ikev2/tasks/ike_delete.h> #include <sa/ikev2/tasks/ike_config.h> #include <sa/ikev2/tasks/ike_dpd.h> @@ -171,6 +172,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; }; /** @@ -510,6 +516,11 @@ METHOD(task_manager_t, initiate, status_t, break; } #endif /* ME */ + if (activate_task(this, TASK_IKE_REAUTH_COMPLETE)) + { + exchange = INFORMATIONAL; + break; + } case IKE_REKEYING: if (activate_task(this, TASK_IKE_DELETE)) { @@ -604,6 +615,11 @@ METHOD(task_manager_t, initiate, status_t, /* update exchange type if a task changed it */ this->initiating.type = message->get_exchange_type(message); + if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED) + { + message->destroy(message); + return SUCCESS; + } if (!generate_message(this, message, &this->initiating.packets)) { @@ -1170,7 +1186,7 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg) { unknown = (unknown_payload_t*)payload; type = payload->get_type(payload); - if (!payload_is_known(type) && + if (!payload_is_known(type, msg->get_major_version(msg)) && unknown->is_critical(unknown)) { DBG1(DBG_ENC, "payload type %N is not supported, " @@ -1288,17 +1304,16 @@ METHOD(task_manager_t, process_message, status_t, { if (mid == this->responding.mid) { - /* reject initial messages once established */ - if (msg->get_exchange_type(msg) == IKE_SA_INIT || - msg->get_exchange_type(msg) == IKE_AUTH) + /* reject initial messages if not received in specific states */ + if ((msg->get_exchange_type(msg) == IKE_SA_INIT && + this->ike_sa->get_state(this->ike_sa) != IKE_CREATED) || + (msg->get_exchange_type(msg) == IKE_AUTH && + this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)) { - if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && - this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) - { - DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", - exchange_type_names, msg->get_exchange_type(msg)); - return FAILED; - } + DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N", + exchange_type_names, msg->get_exchange_type(msg), + ike_sa_state_names, this->ike_sa->get_state(this->ike_sa)); + return FAILED; } if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) { /* with MOBIKE, we do no implicit updates */ @@ -1339,10 +1354,6 @@ METHOD(task_manager_t, process_message, status_t, { DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", mid, this->responding.mid); - if (msg->get_exchange_type(msg) == IKE_SA_INIT) - { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ - return DESTROY_ME; - } } } else @@ -1505,9 +1516,79 @@ 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) + { + new->queue_task(new, (task_t*)ike_reauth_complete_create(new, + this->ike_sa->get_id(this->ike_sa))); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, new); + } + 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 +1854,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; |