From 15a682f4c23d0b8340b31077698e6f6d924c2861 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 19 Dec 2011 13:10:29 +0100 Subject: Separated libcharon/sa directory with ikev1 and ikev2 subfolders --- src/libcharon/sa/ikev1/tasks/xauth.c | 399 +++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 src/libcharon/sa/ikev1/tasks/xauth.c (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c new file mode 100644 index 000000000..b4d690094 --- /dev/null +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "xauth.h" + +#include +#include +#include + +typedef struct private_xauth_t private_xauth_t; + +/** + * Status types exchanged + */ +typedef enum { + XAUTH_FAILED = 0, + XAUTH_OK = 1, +} xauth_status_t; + +/** + * Private members of a xauth_t task. + */ +struct private_xauth_t { + + /** + * Public methods and task_t interface. + */ + xauth_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Are we the XAUTH initiator? + */ + bool initiator; + + /** + * XAuth backend to use + */ + xauth_method_t *xauth; + + /** + * XAuth username + */ + identification_t *user; + + /** + * Generated configuration payload + */ + cp_payload_t *cp; + + /** + * status of Xauth exchange + */ + xauth_status_t status; +}; + +/** + * Load XAuth backend + */ +static xauth_method_t *load_method(private_xauth_t* this) +{ + identification_t *server, *peer; + enumerator_t *enumerator; + xauth_method_t *xauth; + xauth_role_t role; + peer_cfg_t *peer_cfg; + auth_cfg_t *auth; + char *name; + + if (this->initiator) + { + server = this->ike_sa->get_my_id(this->ike_sa); + peer = this->ike_sa->get_other_id(this->ike_sa); + role = XAUTH_SERVER; + } + else + { + peer = this->ike_sa->get_my_id(this->ike_sa); + server = this->ike_sa->get_other_id(this->ike_sa); + role = XAUTH_PEER; + } + peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, !this->initiator); + if (!enumerator->enumerate(enumerator, &auth) || + (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH) + { + if (!enumerator->enumerate(enumerator, &auth) || + (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_XAUTH) + { + DBG1(DBG_CFG, "no XAuth authentication round found"); + enumerator->destroy(enumerator); + return NULL; + } + } + name = auth->get(auth, AUTH_RULE_XAUTH_BACKEND); + this->user = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY); + if (!this->initiator && this->user) + { /* use XAUTH username, if configured */ + peer = this->user; + } + enumerator->destroy(enumerator); + xauth = charon->xauth->create_instance(charon->xauth, name, role, + server, peer); + if (!xauth) + { + if (name) + { + DBG1(DBG_CFG, "no XAuth method found named '%s'"); + } + else + { + DBG1(DBG_CFG, "no XAuth method found"); + } + } + return xauth; +} + +/** + * Set IKE_SA to established state + */ +static void establish(private_xauth_t *this) +{ + 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); +} + +METHOD(task_t, build_i_status, status_t, + private_xauth_t *this, message_t *message) +{ + cp_payload_t *cp; + + cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET); + cp->add_attribute(cp, + configuration_attribute_create_value(XAUTH_STATUS, this->status)); + + message->add_payload(message, (payload_t *)cp); + + return NEED_MORE; +} + +METHOD(task_t, build_i, status_t, + private_xauth_t *this, message_t *message) +{ + if (!this->xauth) + { + cp_payload_t *cp; + + this->xauth = load_method(this); + if (!this->xauth) + { + return FAILED; + } + if (this->xauth->initiate(this->xauth, &cp) != NEED_MORE) + { + return FAILED; + } + message->add_payload(message, (payload_t *)cp); + return NEED_MORE; + } + + if (this->cp) + { /* send previously generated payload */ + message->add_payload(message, (payload_t *)this->cp); + this->cp = NULL; + return NEED_MORE; + } + return FAILED; +} + +METHOD(task_t, build_r_ack, status_t, + private_xauth_t *this, message_t *message) +{ + cp_payload_t *cp; + + cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK); + cp->add_attribute(cp, + configuration_attribute_create_chunk( + CONFIGURATION_ATTRIBUTE_V1, XAUTH_STATUS, chunk_empty)); + + message->add_payload(message, (payload_t *)cp); + + if (this->status == XAUTH_OK) + { + establish(this); + return SUCCESS; + } + return FAILED; +} + +METHOD(task_t, process_r, status_t, + private_xauth_t *this, message_t *message) +{ + cp_payload_t *cp; + + if (!this->xauth) + { + this->xauth = load_method(this); + if (!this->xauth) + { /* send empty reply */ + return NEED_MORE; + } + } + cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1); + if (!cp) + { + DBG1(DBG_IKE, "configuration payload missing in XAuth request"); + return FAILED; + } + if (cp->get_type(cp) == CFG_REQUEST) + { + switch (this->xauth->process(this->xauth, cp, &this->cp)) + { + case NEED_MORE: + return NEED_MORE; + case SUCCESS: + case FAILED: + default: + break; + } + this->cp = NULL; + return NEED_MORE; + } + if (cp->get_type(cp) == CFG_SET) + { + configuration_attribute_t *attribute; + enumerator_t *enumerator; + + enumerator = cp->create_attribute_enumerator(cp); + while (enumerator->enumerate(enumerator, &attribute)) + { + if (attribute->get_type(attribute) == XAUTH_STATUS) + { + this->status = attribute->get_value(attribute); + } + } + enumerator->destroy(enumerator); + if (this->status == XAUTH_OK) + { + DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful", + this->xauth->get_identity(this->xauth)); + establish(this); + } + else + { + DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) failed", + this->xauth->get_identity(this->xauth)); + } + } + this->public.task.build = _build_r_ack; + return NEED_MORE; +} + +METHOD(task_t, build_r, status_t, + private_xauth_t *this, message_t *message) +{ + if (!this->cp) + { /* send empty reply if building data failed */ + this->cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY); + } + message->add_payload(message, (payload_t *)this->cp); + this->cp = NULL; + return NEED_MORE; +} + +METHOD(task_t, process_i_status, status_t, + private_xauth_t *this, message_t *message) +{ + cp_payload_t *cp; + + cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1); + if (!cp || cp->get_type(cp) != CFG_ACK) + { + DBG1(DBG_IKE, "received invalid XAUTH status response"); + return FAILED; + } + if (this->status != XAUTH_OK) + { + DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication"); + return FAILED; + } + establish(this); + return SUCCESS; +} + +METHOD(task_t, process_i, status_t, + private_xauth_t *this, message_t *message) +{ + identification_t *id; + cp_payload_t *cp; + + cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1); + if (!cp) + { + DBG1(DBG_IKE, "configuration payload missing in XAuth response"); + return FAILED; + } + switch (this->xauth->process(this->xauth, cp, &this->cp)) + { + case NEED_MORE: + return NEED_MORE; + case SUCCESS: + id = this->xauth->get_identity(this->xauth); + if (this->user && !id->matches(id, this->user)) + { + DBG1(DBG_IKE, "XAuth username '%Y' does not match to " + "configured username '%Y'", id, this->user); + break; + } + DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id); + this->status = XAUTH_OK; + break; + case FAILED: + DBG1(DBG_IKE, "XAuth authentication of '%Y' failed", + this->xauth->get_identity(this->xauth)); + break; + default: + return FAILED; + } + this->public.task.build = _build_i_status; + this->public.task.process = _process_i_status; + return NEED_MORE; +} + +METHOD(task_t, get_type, task_type_t, + private_xauth_t *this) +{ + return TASK_XAUTH; +} + +METHOD(task_t, migrate, void, + private_xauth_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +METHOD(task_t, destroy, void, + private_xauth_t *this) +{ + DESTROY_IF(this->xauth); + DESTROY_IF(this->cp); + free(this); +} + +/* + * Described in header. + */ +xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator) +{ + private_xauth_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .migrate = _migrate, + .destroy = _destroy, + }, + }, + .initiator = initiator, + .ike_sa = ike_sa, + .status = XAUTH_FAILED, + ); + + if (initiator) + { + this->public.task.build = _build_i; + this->public.task.process = _process_i; + } + else + { + this->public.task.build = _build_r; + this->public.task.process = _process_r; + } + return &this->public; +} -- cgit v1.2.3 From ca037076bfd31578410af900a3a667efa165df78 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 20 Dec 2011 18:00:57 +0100 Subject: Implemented migration of XAuth task --- src/libcharon/sa/ikev1/tasks/xauth.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index b4d690094..f55299398 100644 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -354,7 +354,25 @@ METHOD(task_t, get_type, task_type_t, METHOD(task_t, migrate, void, private_xauth_t *this, ike_sa_t *ike_sa) { + DESTROY_IF(this->xauth); + DESTROY_IF(this->cp); + this->ike_sa = ike_sa; + this->xauth = NULL; + this->cp = NULL; + this->user = NULL; + this->status = XAUTH_FAILED; + + if (this->initiator) + { + this->public.task.build = _build_i; + this->public.task.process = _process_i; + } + else + { + this->public.task.build = _build_r; + this->public.task.process = _process_r; + } } METHOD(task_t, destroy, void, -- cgit v1.2.3 From d71092ceed514b312b4bbd2a1b9e2300e256d1f7 Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Thu, 29 Dec 2011 00:06:12 +0100 Subject: Setting Mode Cfg identifier for CFG_ACK messages. --- src/libcharon/sa/ikev1/tasks/xauth.c | 7 +++++++ 1 file changed, 7 insertions(+) mode change 100644 => 100755 src/libcharon/sa/ikev1/tasks/xauth.c (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c old mode 100644 new mode 100755 index f55299398..20d6d8a17 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -64,6 +64,11 @@ struct private_xauth_t { */ cp_payload_t *cp; + /** + * received identifier + */ + u_int16_t identifier; + /** * status of Xauth exchange */ @@ -197,6 +202,7 @@ METHOD(task_t, build_r_ack, status_t, cp_payload_t *cp; cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK); + cp->set_identifier(cp, this->identifier); cp->add_attribute(cp, configuration_attribute_create_chunk( CONFIGURATION_ATTRIBUTE_V1, XAUTH_STATUS, chunk_empty)); @@ -270,6 +276,7 @@ METHOD(task_t, process_r, status_t, this->xauth->get_identity(this->xauth)); } } + this->identifier = cp->get_identifier(cp); this->public.task.build = _build_r_ack; return NEED_MORE; } -- cgit v1.2.3 From 2da3ff7a5235cd86146a02e0a57f63a1a2b8e3e8 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 3 Jan 2012 11:27:41 +0100 Subject: Set a condition flag if peer has been authenticated using XAuth --- src/libcharon/sa/ikev1/tasks/xauth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index 20d6d8a17..7e7e84a8e 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -310,6 +310,7 @@ METHOD(task_t, process_i_status, status_t, return FAILED; } establish(this); + this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE); return SUCCESS; } -- cgit v1.2.3 From 17c64d5ff9bd2076883f4d5eea23923e61b857ff Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 3 Jan 2012 11:59:21 +0100 Subject: Establish IKE_SA only once as XAuth responder --- src/libcharon/sa/ikev1/tasks/xauth.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index 7e7e84a8e..8d8744b3d 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -268,7 +268,6 @@ METHOD(task_t, process_r, status_t, { DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful", this->xauth->get_identity(this->xauth)); - establish(this); } else { -- cgit v1.2.3 From b147679a2c1b3c232a13f8f58418b4976571b8da Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 4 Jan 2012 17:51:22 +0100 Subject: Try to detect reauthentication as responder and adopt children to new SA --- src/libcharon/sa/ikev1/tasks/xauth.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index 8d8744b3d..e836bed16 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -18,6 +18,7 @@ #include #include #include +#include typedef struct private_xauth_t private_xauth_t; @@ -212,6 +213,8 @@ METHOD(task_t, build_r_ack, status_t, if (this->status == XAUTH_OK) { establish(this); + lib->processor->queue_job(lib->processor, (job_t*) + adopt_children_job_create(this->ike_sa->get_id(this->ike_sa))); return SUCCESS; } return FAILED; -- cgit v1.2.3 From f420f51f55f3641553411b74f4925bd9f64116b5 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 18 Jan 2012 13:12:07 +0100 Subject: Invoke authorization hooks for IKEv1 connections --- src/libcharon/sa/ikev1/tasks/xauth.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index e836bed16..aa79811f7 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -140,8 +140,19 @@ static xauth_method_t *load_method(private_xauth_t* this) /** * Set IKE_SA to established state */ -static void establish(private_xauth_t *this) +static bool establish(private_xauth_t *this) { + if (!charon->bus->authorize(charon->bus, FALSE)) + { + DBG1(DBG_IKE, "XAuth authorization hook forbids IKE_SA, cancelling"); + return FALSE; + } + if (!charon->bus->authorize(charon->bus, TRUE)) + { + DBG1(DBG_IKE, "final authorization hook forbids IKE_SA, cancelling"); + return FALSE; + } + 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), @@ -152,6 +163,8 @@ static void establish(private_xauth_t *this) this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); charon->bus->ike_updown(charon->bus, this->ike_sa, TRUE); + + return TRUE; } METHOD(task_t, build_i_status, status_t, @@ -210,9 +223,8 @@ METHOD(task_t, build_r_ack, status_t, message->add_payload(message, (payload_t *)cp); - if (this->status == XAUTH_OK) + if (this->status == XAUTH_OK && establish(this)) { - establish(this); lib->processor->queue_job(lib->processor, (job_t*) adopt_children_job_create(this->ike_sa->get_id(this->ike_sa))); return SUCCESS; @@ -311,7 +323,10 @@ METHOD(task_t, process_i_status, status_t, DBG1(DBG_IKE, "destroying IKE_SA after failed XAuth authentication"); return FAILED; } - establish(this); + if (!establish(this)) + { + return FAILED; + } this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE); return SUCCESS; } -- cgit v1.2.3 From 83d77866f476ed0968283a8a8f349c48d92a1158 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 21 Mar 2012 16:57:06 +0100 Subject: Store authentication info of a XAUTH round on IKE_SA --- src/libcharon/sa/ikev1/tasks/xauth.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/libcharon/sa/ikev1/tasks/xauth.c') diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c index aa79811f7..059877edd 100755 --- a/src/libcharon/sa/ikev1/tasks/xauth.c +++ b/src/libcharon/sa/ikev1/tasks/xauth.c @@ -167,6 +167,20 @@ static bool establish(private_xauth_t *this) return TRUE; } +/** + * Create auth config after successful authentication + */ +static void add_auth_cfg(private_xauth_t *this, identification_t *id, bool local) +{ + auth_cfg_t *auth; + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH); + auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id)); + + this->ike_sa->add_auth_cfg(this->ike_sa, local, auth); +} + METHOD(task_t, build_i_status, status_t, private_xauth_t *this, message_t *message) { @@ -283,6 +297,7 @@ METHOD(task_t, process_r, status_t, { DBG1(DBG_IKE, "XAuth authentication of '%Y' (myself) successful", this->xauth->get_identity(this->xauth)); + add_auth_cfg(this, this->xauth->get_identity(this->xauth), TRUE); } else { @@ -356,6 +371,7 @@ METHOD(task_t, process_i, status_t, break; } DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id); + add_auth_cfg(this, id, FALSE); this->status = XAUTH_OK; break; case FAILED: -- cgit v1.2.3