diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-05-21 12:07:17 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-05-21 15:49:25 +0200 |
commit | 1a624ff45a4dcab2167491ad3ecc2e6f3f2e22c8 (patch) | |
tree | 48b28d59f1320c27d0fa9a8bf1a6805e469e5103 /src/libcharon | |
parent | 17949695bfd986c1cf32eee0460f02528026bbb9 (diff) | |
download | strongswan-1a624ff45a4dcab2167491ad3ecc2e6f3f2e22c8.tar.bz2 strongswan-1a624ff45a4dcab2167491ad3ecc2e6f3f2e22c8.tar.xz |
Switch to alternative peer config in IKEv1 Main and Aggressive Mode.
Diffstat (limited to 'src/libcharon')
-rw-r--r-- | src/libcharon/sa/ikev1/phase1.c | 53 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/phase1.h | 3 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/aggressive_mode.c | 23 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/main_mode.c | 30 |
4 files changed, 85 insertions, 24 deletions
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c index ec55d533d..709bc6cbc 100644 --- a/src/libcharon/sa/ikev1/phase1.c +++ b/src/libcharon/sa/ikev1/phase1.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG * @@ -19,6 +22,7 @@ #include <sa/ikev1/keymat_v1.h> #include <encoding/payloads/ke_payload.h> #include <encoding/payloads/nonce_payload.h> +#include <utils/linked_list.h> typedef struct private_phase1_t private_phase1_t; @@ -38,6 +42,16 @@ struct private_phase1_t { ike_sa_t *ike_sa; /** + * Currently selected peer config + */ + peer_cfg_t *peer_cfg; + + /** + * Other possible peer config candidates + */ + linked_list_t *candidates; + + /** * Acting as initiator */ bool initiator; @@ -513,9 +527,22 @@ METHOD(phase1_t, select_config, peer_cfg_t*, identification_t *id) { enumerator_t *enumerator; - peer_cfg_t *current, *found = NULL; + peer_cfg_t *current; host_t *me, *other; + if (this->peer_cfg) + { /* try to find an alternative config */ + if (this->candidates->remove_first(this->candidates, + (void**)¤t) != SUCCESS) + { + DBG1(DBG_CFG, "no alternative config found"); + return NULL; + } + DBG1(DBG_CFG, "switching to peer config '%s'", + current->get_name(current)); + return current; + } + me = this->ike_sa->get_my_host(this->ike_sa); other = this->ike_sa->get_other_host(this->ike_sa); DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]", @@ -527,17 +554,27 @@ METHOD(phase1_t, select_config, peer_cfg_t*, if (check_auth_method(this, current, method) && current->use_aggressive(current) == aggressive) { - found = current->get_ref(current); - break; + current->get_ref(current); + if (!this->peer_cfg) + { + this->peer_cfg = current; + } + else + { + this->candidates->insert_last(this->candidates, current); + } } } enumerator->destroy(enumerator); - if (found) + if (this->peer_cfg) { - DBG2(DBG_CFG, "selected peer config \"%s\"", found->get_name(found)); + DBG1(DBG_CFG, "selected peer config \"%s\"", + this->peer_cfg->get_name(this->peer_cfg)); + return this->peer_cfg->get_ref(this->peer_cfg); } - return found; + DBG1(DBG_IKE, "no peer config found"); + return NULL; } METHOD(phase1_t, get_id, identification_t*, @@ -661,6 +698,9 @@ METHOD(phase1_t, get_nonce_ke, bool, METHOD(phase1_t, destroy, void, private_phase1_t *this) { + DESTROY_IF(this->peer_cfg); + this->candidates->destroy_offset(this->candidates, + offsetof(peer_cfg_t, destroy)); chunk_free(&this->sa_payload); DESTROY_IF(this->dh); free(this->dh_value.ptr); @@ -691,6 +731,7 @@ phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator) .get_nonce_ke = _get_nonce_ke, .destroy = _destroy, }, + .candidates = linked_list_create(), .ike_sa = ike_sa, .initiator = initiator, .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa), diff --git a/src/libcharon/sa/ikev1/phase1.h b/src/libcharon/sa/ikev1/phase1.h index 91210c31f..f1e95d88c 100644 --- a/src/libcharon/sa/ikev1/phase1.h +++ b/src/libcharon/sa/ikev1/phase1.h @@ -88,6 +88,9 @@ struct phase1_t { /** * Select a peer config as responder. * + * If called after the first successful call the next alternative config + * is returned, if any. + * * @param method used authentication method * @param aggressive TRUE to get an aggressive mode config * @param id initiator identity diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c index 4c581cdb6..e1c51a865 100644 --- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c +++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2012 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG * @@ -399,7 +402,6 @@ METHOD(task_t, process_r, status_t, this->method, TRUE, id); if (!this->peer_cfg) { - DBG1(DBG_IKE, "no peer config found"); return send_notify(this, AUTHENTICATION_FAILED); } this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); @@ -413,11 +415,22 @@ METHOD(task_t, process_r, status_t, } case AM_AUTH: { - if (!this->ph1->verify_auth(this->ph1, this->method, message, - this->id_data)) + while (TRUE) { - this->id_data = chunk_empty; - return send_delete(this); + if (this->ph1->verify_auth(this->ph1, this->method, message, + this->id_data)) + { + break; + } + this->peer_cfg->destroy(this->peer_cfg); + this->peer_cfg = this->ph1->select_config(this->ph1, + this->method, TRUE, NULL); + if (!this->peer_cfg) + { + this->id_data = chunk_empty; + return send_delete(this); + } + this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); } this->id_data = chunk_empty; diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index ff78764da..ce047df16 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Tobias Brunner + * Copyright (C) 2011-2012 Tobias Brunner * Hochschule fuer Technik Rapperswil * * Copyright (C) 2011 Martin Willi @@ -405,23 +405,27 @@ METHOD(task_t, process_r, status_t, DBG1(DBG_IKE, "IDii payload missing"); return send_notify(this, INVALID_PAYLOAD_TYPE); } - id = id_payload->get_identification(id_payload); this->ike_sa->set_other_id(this->ike_sa, id); - this->peer_cfg = this->ph1->select_config(this->ph1, - this->method, FALSE, id); - if (!this->peer_cfg) - { - DBG1(DBG_IKE, "no peer config found"); - return send_notify(this, AUTHENTICATION_FAILED); - } - this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); - if (!this->ph1->verify_auth(this->ph1, this->method, message, - id_payload->get_encoded(id_payload))) + while (TRUE) { - return send_notify(this, AUTHENTICATION_FAILED); + DESTROY_IF(this->peer_cfg); + this->peer_cfg = this->ph1->select_config(this->ph1, + this->method, FALSE, id); + if (!this->peer_cfg) + { + return send_notify(this, AUTHENTICATION_FAILED); + } + this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg); + + if (this->ph1->verify_auth(this->ph1, this->method, message, + id_payload->get_encoded(id_payload))) + { + break; + } } + if (!charon->bus->authorize(charon->bus, FALSE)) { DBG1(DBG_IKE, "Main Mode authorization hook forbids IKE_SA, " |