Switch to alternative peer config in IKEv1 Main and Aggressive Mode.
This commit is contained in:
parent
17949695bf
commit
1a624ff45a
|
@ -1,4 +1,7 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2012 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2012 Martin Willi
|
* Copyright (C) 2012 Martin Willi
|
||||||
* Copyright (C) 2012 revosec AG
|
* Copyright (C) 2012 revosec AG
|
||||||
*
|
*
|
||||||
|
@ -19,6 +22,7 @@
|
||||||
#include <sa/ikev1/keymat_v1.h>
|
#include <sa/ikev1/keymat_v1.h>
|
||||||
#include <encoding/payloads/ke_payload.h>
|
#include <encoding/payloads/ke_payload.h>
|
||||||
#include <encoding/payloads/nonce_payload.h>
|
#include <encoding/payloads/nonce_payload.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
typedef struct private_phase1_t private_phase1_t;
|
typedef struct private_phase1_t private_phase1_t;
|
||||||
|
|
||||||
|
@ -37,6 +41,16 @@ struct private_phase1_t {
|
||||||
*/
|
*/
|
||||||
ike_sa_t *ike_sa;
|
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
|
* Acting as initiator
|
||||||
*/
|
*/
|
||||||
|
@ -513,9 +527,22 @@ METHOD(phase1_t, select_config, peer_cfg_t*,
|
||||||
identification_t *id)
|
identification_t *id)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
peer_cfg_t *current, *found = NULL;
|
peer_cfg_t *current;
|
||||||
host_t *me, *other;
|
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);
|
me = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
other = this->ike_sa->get_other_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]",
|
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) &&
|
if (check_auth_method(this, current, method) &&
|
||||||
current->use_aggressive(current) == aggressive)
|
current->use_aggressive(current) == aggressive)
|
||||||
{
|
{
|
||||||
found = current->get_ref(current);
|
current->get_ref(current);
|
||||||
break;
|
if (!this->peer_cfg)
|
||||||
|
{
|
||||||
|
this->peer_cfg = current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->candidates->insert_last(this->candidates, current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
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*,
|
METHOD(phase1_t, get_id, identification_t*,
|
||||||
|
@ -661,6 +698,9 @@ METHOD(phase1_t, get_nonce_ke, bool,
|
||||||
METHOD(phase1_t, destroy, void,
|
METHOD(phase1_t, destroy, void,
|
||||||
private_phase1_t *this)
|
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);
|
chunk_free(&this->sa_payload);
|
||||||
DESTROY_IF(this->dh);
|
DESTROY_IF(this->dh);
|
||||||
free(this->dh_value.ptr);
|
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,
|
.get_nonce_ke = _get_nonce_ke,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
|
.candidates = linked_list_create(),
|
||||||
.ike_sa = ike_sa,
|
.ike_sa = ike_sa,
|
||||||
.initiator = initiator,
|
.initiator = initiator,
|
||||||
.keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
|
.keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
|
||||||
|
|
|
@ -88,6 +88,9 @@ struct phase1_t {
|
||||||
/**
|
/**
|
||||||
* Select a peer config as responder.
|
* 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 method used authentication method
|
||||||
* @param aggressive TRUE to get an aggressive mode config
|
* @param aggressive TRUE to get an aggressive mode config
|
||||||
* @param id initiator identity
|
* @param id initiator identity
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2012 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2012 Martin Willi
|
* Copyright (C) 2012 Martin Willi
|
||||||
* Copyright (C) 2012 revosec AG
|
* Copyright (C) 2012 revosec AG
|
||||||
*
|
*
|
||||||
|
@ -399,7 +402,6 @@ METHOD(task_t, process_r, status_t,
|
||||||
this->method, TRUE, id);
|
this->method, TRUE, id);
|
||||||
if (!this->peer_cfg)
|
if (!this->peer_cfg)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "no peer config found");
|
|
||||||
return send_notify(this, AUTHENTICATION_FAILED);
|
return send_notify(this, AUTHENTICATION_FAILED);
|
||||||
}
|
}
|
||||||
this->ike_sa->set_peer_cfg(this->ike_sa, this->peer_cfg);
|
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:
|
case AM_AUTH:
|
||||||
{
|
{
|
||||||
if (!this->ph1->verify_auth(this->ph1, this->method, message,
|
while (TRUE)
|
||||||
this->id_data))
|
|
||||||
{
|
{
|
||||||
this->id_data = chunk_empty;
|
if (this->ph1->verify_auth(this->ph1, this->method, message,
|
||||||
return send_delete(this);
|
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;
|
this->id_data = chunk_empty;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Tobias Brunner
|
* Copyright (C) 2011-2012 Tobias Brunner
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Martin Willi
|
* Copyright (C) 2011 Martin Willi
|
||||||
|
@ -405,23 +405,27 @@ METHOD(task_t, process_r, status_t,
|
||||||
DBG1(DBG_IKE, "IDii payload missing");
|
DBG1(DBG_IKE, "IDii payload missing");
|
||||||
return send_notify(this, INVALID_PAYLOAD_TYPE);
|
return send_notify(this, INVALID_PAYLOAD_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
id = id_payload->get_identification(id_payload);
|
id = id_payload->get_identification(id_payload);
|
||||||
this->ike_sa->set_other_id(this->ike_sa, id);
|
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,
|
while (TRUE)
|
||||||
id_payload->get_encoded(id_payload)))
|
|
||||||
{
|
{
|
||||||
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))
|
if (!charon->bus->authorize(charon->bus, FALSE))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "Main Mode authorization hook forbids IKE_SA, "
|
DBG1(DBG_IKE, "Main Mode authorization hook forbids IKE_SA, "
|
||||||
|
|
Loading…
Reference in New Issue