aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2012-05-21 12:07:17 +0200
committerTobias Brunner <tobias@strongswan.org>2012-05-21 15:49:25 +0200
commit1a624ff45a4dcab2167491ad3ecc2e6f3f2e22c8 (patch)
tree48b28d59f1320c27d0fa9a8bf1a6805e469e5103 /src/libcharon
parent17949695bfd986c1cf32eee0460f02528026bbb9 (diff)
downloadstrongswan-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.c53
-rw-r--r--src/libcharon/sa/ikev1/phase1.h3
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c23
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c30
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**)&current) != 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, "