diff options
Diffstat (limited to 'src/libcharon/plugins/xauth_eap')
-rw-r--r-- | src/libcharon/plugins/xauth_eap/Makefile.am | 17 | ||||
-rw-r--r-- | src/libcharon/plugins/xauth_eap/xauth_eap.c | 288 | ||||
-rw-r--r-- | src/libcharon/plugins/xauth_eap/xauth_eap.h | 55 | ||||
-rw-r--r-- | src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c | 60 | ||||
-rw-r--r-- | src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h | 42 |
5 files changed, 462 insertions, 0 deletions
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.am b/src/libcharon/plugins/xauth_eap/Makefile.am new file mode 100644 index 000000000..f2cb0e26c --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-xauth-eap.la +else +plugin_LTLIBRARIES = libstrongswan-xauth-eap.la +endif + +libstrongswan_xauth_eap_la_SOURCES = \ + xauth_eap_plugin.h xauth_eap_plugin.c \ + xauth_eap.h xauth_eap.c + +libstrongswan_xauth_eap_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.c b/src/libcharon/plugins/xauth_eap/xauth_eap.c new file mode 100644 index 000000000..8d7bcc0c0 --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap.c @@ -0,0 +1,288 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_eap.h" + +#include <daemon.h> + +#include <library.h> +#include <credentials/sets/callback_cred.h> + +typedef struct private_xauth_eap_t private_xauth_eap_t; + +/** + * Private data of an xauth_eap_t object. + */ +struct private_xauth_eap_t { + + /** + * Public interface. + */ + xauth_eap_t public; + + /** + * ID of the server + */ + identification_t *server; + + /** + * ID of the peer + */ + identification_t *peer; + + /** + * Callback credential set + */ + callback_cred_t *cred; + + /** + * XAuth password + */ + chunk_t pass; +}; + +/** + * Callback credential set function + */ +static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type, + identification_t *me, identification_t *other, + id_match_t *match_me, id_match_t *match_other) +{ + shared_key_t *shared; + + if (!this->pass.len) + { + return NULL; + } + if (type != SHARED_EAP && type != SHARED_ANY) + { + return NULL; + } + if (me) + { + if (!this->peer->equals(this->peer, me)) + { + return NULL; + } + if (match_me) + { + *match_me = ID_MATCH_PERFECT; + } + } + else if (match_me) + { + *match_me = ID_MATCH_ANY; + } + if (other) + { + if (!this->server->equals(this->server, other)) + { + return NULL; + } + if (match_other) + { + *match_other = ID_MATCH_PERFECT; + } + } + else if (match_other) + { + *match_other = ID_MATCH_ANY; + } + shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass)); + this->pass = chunk_empty; + return shared; +} + +/** + * Do EAP exchanges to verify secret + */ +static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend) +{ + eap_payload_t *request, *response; + eap_method_t *frontend; + eap_type_t type; + u_int32_t vendor; + status_t status; + + if (backend->initiate(backend, &request) != NEED_MORE) + { + return FALSE; + } + type = request->get_type(request, &vendor); + frontend = charon->eap->create_instance(charon->eap, type, vendor, + EAP_PEER, this->server, this->peer); + if (!frontend) + { + DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported", + eap_type_names, type); + request->destroy(request); + return FALSE; + } + while (TRUE) + { + /* credential set is active in frontend only, but not in backend */ + lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE); + status = frontend->process(frontend, request, &response); + lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set); + request->destroy(request); + if (status != NEED_MORE) + { /* clients should never return SUCCESS */ + frontend->destroy(frontend); + return FALSE; + } + status = backend->process(backend, response, &request); + response->destroy(response); + switch (status) + { + case SUCCESS: + frontend->destroy(frontend); + return TRUE; + case NEED_MORE: + break; + default: + frontend->destroy(frontend); + return FALSE; + } + } +} + +METHOD(xauth_method_t, initiate, status_t, + private_xauth_eap_t *this, cp_payload_t **out) +{ + cp_payload_t *cp; + + cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST); + cp->add_attribute(cp, configuration_attribute_create_chunk( + CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty)); + cp->add_attribute(cp, configuration_attribute_create_chunk( + CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty)); + *out = cp; + return NEED_MORE; +} + +METHOD(xauth_method_t, process, status_t, + private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out) +{ + configuration_attribute_t *attr; + enumerator_t *enumerator; + identification_t *id; + chunk_t user = chunk_empty; + eap_method_t *backend; + eap_type_t type; + char *name; + bool ok; + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &attr)) + { + switch (attr->get_type(attr)) + { + case XAUTH_USER_NAME: + user = attr->get_chunk(attr); + break; + case XAUTH_USER_PASSWORD: + this->pass = attr->get_chunk(attr); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (!user.ptr || !this->pass.ptr) + { + DBG1(DBG_IKE, "peer did not respond to our XAuth request"); + return FAILED; + } + if (user.len) + { + id = identification_create_from_data(user); + if (!id) + { + DBG1(DBG_IKE, "failed to parse provided XAuth username"); + return FAILED; + } + this->peer->destroy(this->peer); + this->peer = id; + } + if (this->pass.len && this->pass.ptr[this->pass.len - 1] == 0) + { /* fix null-terminated passwords (Android etc.) */ + this->pass.len -= 1; + } + + name = lib->settings->get_str(lib->settings, + "charon.plugins.xauth-eap.backend", "radius"); + type = eap_type_from_string(name); + if (!type) + { + DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name); + return FAILED; + } + backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER, + this->server, this->peer); + if (!backend) + { + DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name); + return FAILED; + } + ok = verify_eap(this, backend); + backend->destroy(backend); + if (ok) + { + return SUCCESS; + } + return FAILED; +} + +METHOD(xauth_method_t, get_identity, identification_t*, + private_xauth_eap_t *this) +{ + return this->peer; +} + +METHOD(xauth_method_t, destroy, void, + private_xauth_eap_t *this) +{ + this->cred->destroy(this->cred); + this->server->destroy(this->server); + this->peer->destroy(this->peer); + free(this); +} + +/* + * Described in header. + */ +xauth_eap_t *xauth_eap_create_server(identification_t *server, + identification_t *peer) +{ + private_xauth_eap_t *this; + + INIT(this, + .public = { + .xauth_method = { + .initiate = _initiate, + .process = _process, + .get_identity = _get_identity, + .destroy = _destroy, + }, + }, + .server = server->clone(server), + .peer = peer->clone(peer), + ); + + this->cred = callback_cred_create_shared((void*)shared_cb, this); + + return &this->public; +} diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.h b/src/libcharon/plugins/xauth_eap/xauth_eap.h new file mode 100644 index 000000000..70927247e --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap.h @@ -0,0 +1,55 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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. + */ + +/** + * @defgroup xauth_eap_i xauth_eap + * @{ @ingroup xauth_eap + */ + +#ifndef XAUTH_EAP_H_ +#define XAUTH_EAP_H_ + +typedef struct xauth_eap_t xauth_eap_t; + +#include <sa/xauth/xauth_method.h> + +/** + * XAuth method that verifies XAuth credentials using EAP methods. + * + * To reuse existing authentication infrastructure, this XAuth method uses + * EAP to verify XAuth Username/Passwords. It is primarily designed to work + * with the EAP-RADIUS backend and can use any password-based EAP method + * over it. The credentials are fed locally on the IKE responder to a EAP + * client which talks to the backend instance, usually a RADIUS server. + */ +struct xauth_eap_t { + + /** + * Implemented xauth_method_t interface. + */ + xauth_method_t xauth_method; +}; + +/** + * Creates the XAuth method using EAP, acting as server. + * + * @param server ID of the XAuth server + * @param peer ID of the XAuth client + * @return xauth_eap_t object + */ +xauth_eap_t *xauth_eap_create_server(identification_t *server, + identification_t *peer); + +#endif /** XAUTH_EAP_H_ @}*/ diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c new file mode 100644 index 000000000..b776ec8ea --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c @@ -0,0 +1,60 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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_eap_plugin.h" +#include "xauth_eap.h" + +#include <daemon.h> + +METHOD(plugin_t, get_name, char*, + xauth_eap_plugin_t *this) +{ + return "xauth-eap"; +} + +METHOD(plugin_t, get_features, int, + xauth_eap_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(xauth_method_register, xauth_eap_create_server), + PLUGIN_PROVIDE(XAUTH_SERVER, "eap"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + xauth_eap_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *xauth_eap_plugin_create() +{ + xauth_eap_plugin_t *this; + + INIT(this, + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + ); + + return &this->plugin; +} diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h new file mode 100644 index 000000000..8ba0628b0 --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h @@ -0,0 +1,42 @@ +/* + * 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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. + */ + +/** + * @defgroup xauth_eap xauth_eap + * @ingroup cplugins + * + * @defgroup xauth_eap_plugin xauth_eap_plugin + * @{ @ingroup xauth_eap + */ + +#ifndef XAUTH_EAP_PLUGIN_H_ +#define XAUTH_EAP_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct xauth_eap_plugin_t xauth_eap_plugin_t; + +/** + * XAuth plugin using EAP to verify credentials. + */ +struct xauth_eap_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** XAUTH_EAP_PLUGIN_H_ @}*/ |