aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c6
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c38
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c29
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_delete.c8
4 files changed, 79 insertions, 2 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 5298abf79..839bdb990 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -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;
}
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 4e66c3f29..d1116d8a1 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -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;
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index e5c3cb849..8f83c4884 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -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;
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_delete.c b/src/libcharon/sa/ikev2/tasks/ike_delete.c
index f127b0c15..9bc62bf2a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_delete.c
@@ -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: