Merge branch 'init-auth-fail'
Properly notifies the responder if authentication of an IKE_SA or installation of a CHILD_SA fails as initiator, keeping SA state on peers consistent.
This commit is contained in:
@@ -849,6 +849,12 @@ static status_t process_request(private_task_manager_t *this,
|
||||
task = (task_t*)ike_auth_lifetime_create(
|
||||
this->ike_sa, FALSE);
|
||||
break;
|
||||
case AUTHENTICATION_FAILED:
|
||||
/* initiator failed to authenticate us.
|
||||
* We use ike_delete to handle this, which
|
||||
* invokes all the required hooks. */
|
||||
task = (task_t*)ike_delete_create(
|
||||
this->ike_sa, FALSE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <encoding/payloads/ts_payload.h>
|
||||
#include <encoding/payloads/nonce_payload.h>
|
||||
#include <encoding/payloads/notify_payload.h>
|
||||
#include <encoding/payloads/delete_payload.h>
|
||||
#include <processing/jobs/delete_ike_sa_job.h>
|
||||
#include <processing/jobs/inactivity_job.h>
|
||||
|
||||
@@ -1159,6 +1160,38 @@ static void raise_alerts(private_child_create_t *this, notify_type_t type)
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(task_t, build_i_delete, status_t,
|
||||
private_child_create_t *this, message_t *message)
|
||||
{
|
||||
message->set_exchange_type(message, INFORMATIONAL);
|
||||
if (this->child_sa)
|
||||
{
|
||||
protocol_id_t proto;
|
||||
delete_payload_t *del;
|
||||
u_int32_t spi;
|
||||
|
||||
proto = this->child_sa->get_protocol(this->child_sa);
|
||||
spi = this->child_sa->get_spi(this->child_sa, TRUE);
|
||||
del = delete_payload_create(DELETE, proto);
|
||||
del->add_spi(del, spi);
|
||||
message->add_payload(message, (payload_t*)del);
|
||||
|
||||
DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
|
||||
protocol_id_names, proto, ntohl(spi));
|
||||
}
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change task to delete the failed CHILD_SA as initiator
|
||||
*/
|
||||
static status_t delete_failed_sa(private_child_create_t *this)
|
||||
{
|
||||
this->public.task.build = _build_i_delete;
|
||||
this->public.task.process = (void*)return_success;
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(task_t, process_i, status_t,
|
||||
private_child_create_t *this, message_t *message)
|
||||
{
|
||||
@@ -1260,7 +1293,7 @@ METHOD(task_t, process_i, status_t,
|
||||
DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
|
||||
" one, no CHILD_SA built");
|
||||
handle_child_sa_failure(this, message);
|
||||
return SUCCESS;
|
||||
return delete_failed_sa(this);
|
||||
}
|
||||
else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
|
||||
{
|
||||
@@ -1273,7 +1306,7 @@ METHOD(task_t, process_i, status_t,
|
||||
DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
|
||||
"no CHILD_SA built");
|
||||
handle_child_sa_failure(this, message);
|
||||
return SUCCESS;
|
||||
return delete_failed_sa(this);
|
||||
}
|
||||
|
||||
if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
|
||||
@@ -1295,6 +1328,7 @@ METHOD(task_t, process_i, status_t,
|
||||
else
|
||||
{
|
||||
handle_child_sa_failure(this, message);
|
||||
return delete_failed_sa(this);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -852,6 +852,33 @@ local_auth_failed:
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an INFORMATIONAL message with an AUTH_FAILED before closing IKE_SA
|
||||
*/
|
||||
static void send_auth_failed_informational(private_ike_auth_t *this,
|
||||
message_t *reply)
|
||||
{
|
||||
message_t *message;
|
||||
packet_t *packet;
|
||||
host_t *host;
|
||||
|
||||
message = message_create(IKEV2_MAJOR_VERSION, IKEV2_MINOR_VERSION);
|
||||
message->set_message_id(message, reply->get_message_id(reply) + 1);
|
||||
host = this->ike_sa->get_my_host(this->ike_sa);
|
||||
message->set_source(message, host->clone(host));
|
||||
host = this->ike_sa->get_other_host(this->ike_sa);
|
||||
message->set_destination(message, host->clone(host));
|
||||
message->set_exchange_type(message, INFORMATIONAL);
|
||||
message->add_notify(message, FALSE, AUTHENTICATION_FAILED, chunk_empty);
|
||||
|
||||
if (this->ike_sa->generate_message(this->ike_sa, message,
|
||||
&packet) == SUCCESS)
|
||||
{
|
||||
charon->sender->send(charon->sender, packet);
|
||||
}
|
||||
message->destroy(message);
|
||||
}
|
||||
|
||||
METHOD(task_t, process_i, status_t,
|
||||
private_ike_auth_t *this, message_t *message)
|
||||
{
|
||||
@@ -1005,6 +1032,7 @@ METHOD(task_t, process_i, status_t,
|
||||
break;
|
||||
default:
|
||||
charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
|
||||
send_auth_failed_informational(this, message);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
@@ -1049,6 +1077,7 @@ METHOD(task_t, process_i, status_t,
|
||||
|
||||
peer_auth_failed:
|
||||
charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED);
|
||||
send_auth_failed_informational(this, message);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,14 @@ METHOD(task_t, process_r, status_t,
|
||||
this->ike_sa->get_other_host(this->ike_sa),
|
||||
this->ike_sa->get_other_id(this->ike_sa));
|
||||
|
||||
if (message->get_exchange_type(message) == INFORMATIONAL &&
|
||||
message->get_notify(message, AUTHENTICATION_FAILED))
|
||||
{
|
||||
/* a late AUTHENTICATION_FAILED notify from the initiator after
|
||||
* we have established the IKE_SA: signal auth failure */
|
||||
charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED);
|
||||
}
|
||||
|
||||
switch (this->ike_sa->get_state(this->ike_sa))
|
||||
{
|
||||
case IKE_ESTABLISHED:
|
||||
|
||||
Reference in New Issue
Block a user