ike-auth: Send REDIRECT notify during IKE_AUTH if requested by providers
To prevent the creation of the CHILD_SA we set a condition on the IKE_SA. We also schedule a delete job in case the client does not terminate the IKE_SA (which is a SHOULD in RFC 5685).
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2012-2015 Tobias Brunner
|
||||
* Copyright (C) 2005-2009 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <encoding/payloads/eap_payload.h>
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
#include <sa/ikev2/authenticators/eap_authenticator.h>
|
||||
#include <processing/jobs/delete_ike_sa_job.h>
|
||||
|
||||
typedef struct private_ike_auth_t private_ike_auth_t;
|
||||
|
||||
@@ -685,6 +686,7 @@ METHOD(task_t, process_r, status_t,
|
||||
METHOD(task_t, build_r, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
identification_t *gateway;
|
||||
auth_cfg_t *cfg;
|
||||
|
||||
if (message->get_exchange_type(message) == IKE_SA_INIT)
|
||||
@@ -817,34 +819,56 @@ METHOD(task_t, build_r, status_t,
|
||||
{
|
||||
this->do_another_auth = FALSE;
|
||||
}
|
||||
if (!this->do_another_auth && !this->expect_another_auth)
|
||||
if (this->do_another_auth || this->expect_another_auth)
|
||||
{
|
||||
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
|
||||
this->ike_sa, FALSE))
|
||||
{
|
||||
DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
|
||||
charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
|
||||
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
|
||||
chunk_empty);
|
||||
return FAILED;
|
||||
}
|
||||
if (!charon->bus->authorize(charon->bus, TRUE))
|
||||
{
|
||||
DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
|
||||
goto peer_auth_failed;
|
||||
}
|
||||
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
|
||||
this->ike_sa->get_name(this->ike_sa),
|
||||
this->ike_sa->get_unique_id(this->ike_sa),
|
||||
this->ike_sa->get_my_host(this->ike_sa),
|
||||
this->ike_sa->get_my_id(this->ike_sa),
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->ike_sa->get_other_id(this->ike_sa));
|
||||
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
|
||||
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
|
||||
return SUCCESS;
|
||||
return NEED_MORE;
|
||||
}
|
||||
return NEED_MORE;
|
||||
|
||||
if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager,
|
||||
this->ike_sa, FALSE))
|
||||
{
|
||||
DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy");
|
||||
charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP);
|
||||
message->add_notify(message, TRUE, AUTHENTICATION_FAILED,
|
||||
chunk_empty);
|
||||
return FAILED;
|
||||
}
|
||||
if (!charon->bus->authorize(charon->bus, TRUE))
|
||||
{
|
||||
DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling");
|
||||
goto peer_auth_failed;
|
||||
}
|
||||
if (this->ike_sa->supports_extension(this->ike_sa, EXT_IKE_REDIRECTION) &&
|
||||
charon->redirect->redirect_on_auth(charon->redirect, this->ike_sa,
|
||||
&gateway))
|
||||
{
|
||||
delete_ike_sa_job_t *job;
|
||||
chunk_t data;
|
||||
|
||||
DBG1(DBG_IKE, "redirecting peer to %Y", gateway);
|
||||
data = redirect_data_create(gateway, chunk_empty);
|
||||
message->add_notify(message, FALSE, REDIRECT, data);
|
||||
gateway->destroy(gateway);
|
||||
chunk_free(&data);
|
||||
/* we use this condition to prevent the CHILD_SA from getting created */
|
||||
this->ike_sa->set_condition(this->ike_sa, COND_REDIRECTED, TRUE);
|
||||
/* if the peer does not delete the SA we do so after a while */
|
||||
job = delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE);
|
||||
lib->scheduler->schedule_job(lib->scheduler, (job_t*)job,
|
||||
lib->settings->get_int(lib->settings,
|
||||
"%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
|
||||
lib->ns));
|
||||
}
|
||||
DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]",
|
||||
this->ike_sa->get_name(this->ike_sa),
|
||||
this->ike_sa->get_unique_id(this->ike_sa),
|
||||
this->ike_sa->get_my_host(this->ike_sa),
|
||||
this->ike_sa->get_my_id(this->ike_sa),
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->ike_sa->get_other_id(this->ike_sa));
|
||||
this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED);
|
||||
charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE);
|
||||
return SUCCESS;
|
||||
|
||||
peer_auth_failed:
|
||||
message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty);
|
||||
|
||||
Reference in New Issue
Block a user