diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2018-02-19 18:17:21 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2018-02-19 18:17:21 +0100 |
commit | 7793611ee71b576dd9c66dee327349fa64e38740 (patch) | |
tree | f1379ec1aed52a3c772874d4ed690b90975b9623 /src/libcharon/sa/ikev2/tasks | |
parent | e1d78dc2faaa06e7c3f71ef674a71e4de2f0758e (diff) | |
download | vyos-strongswan-7793611ee71b576dd9c66dee327349fa64e38740.tar.gz vyos-strongswan-7793611ee71b576dd9c66dee327349fa64e38740.zip |
New upstream version 5.6.2
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 35 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.h | 12 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_rekey.c | 12 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_init.c | 71 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_mobike.c | 71 |
5 files changed, 140 insertions, 61 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 4d4d72e0b..85dac6d59 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2017 Tobias Brunner + * Copyright (C) 2008-2018 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * HSR Hochschule fuer Technik Rapperswil @@ -277,12 +277,13 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host) } /** - * Allocate SPIs and update proposals + * Allocate SPIs and update proposals, we also promote the selected DH group */ static bool allocate_spi(private_child_create_t *this) { enumerator_t *enumerator; proposal_t *proposal; + linked_list_t *other_dh_groups; if (this->initiator) { @@ -304,12 +305,29 @@ static bool allocate_spi(private_child_create_t *this) { if (this->initiator) { + other_dh_groups = linked_list_create(); enumerator = this->proposals->create_enumerator(this->proposals); while (enumerator->enumerate(enumerator, &proposal)) { proposal->set_spi(proposal, this->my_spi); + + /* move the selected DH group to the front, if any */ + if (this->dh_group != MODP_NONE && + !proposal->promote_dh_group(proposal, this->dh_group)) + { /* proposals that don't contain the selected group are + * moved to the back */ + this->proposals->remove_at(this->proposals, enumerator); + other_dh_groups->insert_last(other_dh_groups, proposal); + } + } + enumerator->destroy(enumerator); + enumerator = other_dh_groups->create_enumerator(other_dh_groups); + while (enumerator->enumerate(enumerator, (void**)&proposal)) + { /* no need to remove from the list as we destroy it anyway*/ + this->proposals->insert_last(this->proposals, proposal); } enumerator->destroy(enumerator); + other_dh_groups->destroy(other_dh_groups); } else { @@ -396,7 +414,7 @@ static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local) } /** - * Substitude any host address with NATed address in traffic selector + * Substitute any host address with NATed address in traffic selector */ static linked_list_t* get_transport_nat_ts(private_child_create_t *this, bool local, linked_list_t *in) @@ -1006,8 +1024,8 @@ METHOD(task_t, build_i, status_t, chunk_empty); return SUCCESS; } - if (!this->retry) - { + if (!this->retry && this->dh_group == MODP_NONE) + { /* during a rekeying the group might already be set */ this->dh_group = this->config->get_dh_group(this->config); } break; @@ -1615,6 +1633,12 @@ METHOD(child_create_t, use_marks, void, this->mark_out = out; } +METHOD(child_create_t, use_dh_group, void, + private_child_create_t *this, diffie_hellman_group_t dh_group) +{ + this->dh_group = dh_group; +} + METHOD(child_create_t, get_child, child_sa_t*, private_child_create_t *this) { @@ -1736,6 +1760,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, .get_lower_nonce = _get_lower_nonce, .use_reqid = _use_reqid, .use_marks = _use_marks, + .use_dh_group = _use_dh_group, .task = { .get_type = _get_type, .migrate = _migrate, diff --git a/src/libcharon/sa/ikev2/tasks/child_create.h b/src/libcharon/sa/ikev2/tasks/child_create.h index f48d7b0a9..59fc6d2d9 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.h +++ b/src/libcharon/sa/ikev2/tasks/child_create.h @@ -1,6 +1,7 @@ /* + * Copyright (C) 2018 Tobias Brunner * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -60,6 +61,15 @@ struct child_create_t { void (*use_marks)(child_create_t *this, u_int in, u_int out); /** + * Initially propose a specific DH group to override configuration. + * + * This is used during rekeying to prefer the previously negotiated group. + * + * @param dh_group DH group to use + */ + void (*use_dh_group)(child_create_t *this, diffie_hellman_group_t dh_group); + + /** * Get the lower of the two nonces, used for rekey collisions. * * @return lower nonce diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index b67e9b80f..f90056658 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 Tobias Brunner + * Copyright (C) 2009-2018 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * HSR Hochschule fuer Technik Rapperswil @@ -190,8 +190,18 @@ METHOD(task_t, build_i, status_t, /* our CHILD_CREATE task does the hard work for us */ if (!this->child_create) { + proposal_t *proposal; + uint16_t dh_group; + this->child_create = child_create_create(this->ike_sa, config->get_ref(config), TRUE, NULL, NULL); + + proposal = this->child_sa->get_proposal(this->child_sa); + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, + &dh_group, NULL)) + { /* reuse the DH group negotiated previously */ + this->child_create->use_dh_group(this->child_create, dh_group); + } } reqid = this->child_sa->get_reqid(this->child_sa); this->child_create->use_reqid(this->child_create, reqid); diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index d75d21715..3d73d728b 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2008-2015 Tobias Brunner + * Copyright (C) 2008-2018 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -282,7 +282,7 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) sa_payload_t *sa_payload; ke_payload_t *ke_payload; nonce_payload_t *nonce_payload; - linked_list_t *proposal_list; + linked_list_t *proposal_list, *other_dh_groups; ike_sa_id_t *id; proposal_t *proposal; enumerator_t *enumerator; @@ -294,16 +294,31 @@ static bool build_payloads(private_ike_init_t *this, message_t *message) if (this->initiator) { proposal_list = this->config->get_proposals(this->config); - if (this->old_sa) + other_dh_groups = linked_list_create(); + enumerator = proposal_list->create_enumerator(proposal_list); + while (enumerator->enumerate(enumerator, (void**)&proposal)) { /* include SPI of new IKE_SA when we are rekeying */ - enumerator = proposal_list->create_enumerator(proposal_list); - while (enumerator->enumerate(enumerator, (void**)&proposal)) + if (this->old_sa) { proposal->set_spi(proposal, id->get_initiator_spi(id)); } - enumerator->destroy(enumerator); + /* move the selected DH group to the front of the proposal */ + if (!proposal->promote_dh_group(proposal, this->dh_group)) + { /* the proposal does not include the group, move to the back */ + proposal_list->remove_at(proposal_list, enumerator); + other_dh_groups->insert_last(other_dh_groups, proposal); + } } + enumerator->destroy(enumerator); + /* add proposals that don't contain the selected group */ + enumerator = other_dh_groups->create_enumerator(other_dh_groups); + while (enumerator->enumerate(enumerator, (void**)&proposal)) + { /* no need to remove from the list as we destroy it anyway*/ + proposal_list->insert_last(proposal_list, proposal); + } + enumerator->destroy(enumerator); + other_dh_groups->destroy(other_dh_groups); sa_payload = sa_payload_create_from_proposals_v2(proposal_list); proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy)); @@ -531,10 +546,30 @@ METHOD(task_t, build_i, status_t, return FAILED; } - /* if the DH group is set via use_dh_group(), we already have a DH object */ + /* if we are retrying after an INVALID_KE_PAYLOAD we already have one */ if (!this->dh) { - this->dh_group = this->config->get_dh_group(this->config); + if (this->old_sa && lib->settings->get_bool(lib->settings, + "%s.prefer_previous_dh_group", TRUE, lib->ns)) + { /* reuse the DH group we used for the old IKE_SA when rekeying */ + proposal_t *proposal; + uint16_t dh_group; + + proposal = this->old_sa->get_proposal(this->old_sa); + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, + &dh_group, NULL)) + { + this->dh_group = dh_group; + } + else + { /* this shouldn't happen, but let's be safe */ + this->dh_group = this->config->get_dh_group(this->config); + } + } + else + { + this->dh_group = this->config->get_dh_group(this->config); + } this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, this->dh_group); if (!this->dh) @@ -544,6 +579,18 @@ METHOD(task_t, build_i, status_t, return FAILED; } } + else if (this->dh->get_dh_group(this->dh) != this->dh_group) + { /* reset DH instance if group changed (INVALID_KE_PAYLOAD) */ + this->dh->destroy(this->dh); + this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, + this->dh_group); + if (!this->dh) + { + DBG1(DBG_IKE, "requested DH group %N not supported", + diffie_hellman_group_names, this->dh_group); + return FAILED; + } + } /* generate nonce only when we are trying the first time */ if (this->my_nonce.ptr == NULL) @@ -929,12 +976,6 @@ METHOD(task_t, migrate, void, this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); this->proposal = NULL; this->dh_failed = FALSE; - if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group) - { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */ - this->dh->destroy(this->dh); - this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, - this->dh_group); - } } METHOD(task_t, destroy, void, diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c index dc0f24fb8..fe41a1cac 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c +++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2010-2014 Tobias Brunner + * Copyright (C) 2010-2018 Tobias Brunner * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -76,14 +76,36 @@ struct private_ike_mobike_t { * additional addresses got updated */ bool addresses_updated; - - /** - * whether the pending updates counter was increased - */ - bool pending_update; }; /** + * Check if a newer MOBIKE update task is queued + */ +static bool is_newer_update_queued(private_ike_mobike_t *this) +{ + enumerator_t *enumerator; + private_ike_mobike_t *mobike; + task_t *task; + bool found = FALSE; + + enumerator = this->ike_sa->create_task_enumerator(this->ike_sa, + TASK_QUEUE_QUEUED); + while (enumerator->enumerate(enumerator, &task)) + { + if (task->get_type(task) == TASK_IKE_MOBIKE) + { + mobike = (private_ike_mobike_t*)task; + /* a queued check or update might invalidate the results of the + * current task */ + found = mobike->check || mobike->update; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** * read notifys from message and evaluate them */ static void process_payloads(private_ike_mobike_t *this, message_t *message) @@ -526,9 +548,8 @@ METHOD(task_t, process_i, status_t, } else if (message->get_exchange_type(message) == INFORMATIONAL) { - if (this->ike_sa->get_pending_updates(this->ike_sa) > 1) + if (is_newer_update_queued(this)) { - /* newer update queued, ignore this one */ return SUCCESS; } if (this->cookie2.ptr) @@ -553,7 +574,7 @@ METHOD(task_t, process_i, status_t, if (this->natd) { this->natd->task.process(&this->natd->task, message); - if (this->natd->has_mapping_changed(this->natd)) + if (!this->update && this->natd->has_mapping_changed(this->natd)) { /* force an update if mappings have changed */ this->update = this->check = TRUE; @@ -615,25 +636,13 @@ METHOD(ike_mobike_t, addresses, void, private_ike_mobike_t *this) { this->address = TRUE; - if (!this->pending_update) - { - this->pending_update = TRUE; - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); - } } METHOD(ike_mobike_t, roam, void, private_ike_mobike_t *this, bool address) { this->check = TRUE; - this->address = address; - if (!this->pending_update) - { - this->pending_update = TRUE; - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); - } + this->address |= address; } METHOD(ike_mobike_t, dpd, void, @@ -643,12 +652,6 @@ METHOD(ike_mobike_t, dpd, void, { this->natd = ike_natd_create(this->ike_sa, this->initiator); } - if (!this->pending_update) - { - this->pending_update = TRUE; - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); - } } METHOD(ike_mobike_t, is_probing, bool, @@ -678,21 +681,11 @@ METHOD(task_t, migrate, void, { this->natd->task.migrate(&this->natd->task, ike_sa); } - if (this->pending_update) - { - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) + 1); - } } METHOD(task_t, destroy, void, private_ike_mobike_t *this) { - if (this->pending_update) - { - this->ike_sa->set_pending_updates(this->ike_sa, - this->ike_sa->get_pending_updates(this->ike_sa) - 1); - } chunk_free(&this->cookie2); if (this->natd) { |