From 85fc1eb640904a93168a2cd9e92432e3df0bfdf7 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 19 Dec 2011 20:21:02 +0100 Subject: [PATCH] Added an XAuth plugin that forwards authentication to EAP methods --- configure.in | 4 + src/libcharon/Makefile.am | 6 + src/libcharon/plugins/xauth_eap/Makefile.am | 17 ++ src/libcharon/plugins/xauth_eap/xauth_eap.c | 284 ++++++++++++++++++ src/libcharon/plugins/xauth_eap/xauth_eap.h | 49 +++ .../plugins/xauth_eap/xauth_eap_plugin.c | 60 ++++ .../plugins/xauth_eap/xauth_eap_plugin.h | 42 +++ 7 files changed, 462 insertions(+) create mode 100644 src/libcharon/plugins/xauth_eap/Makefile.am create mode 100644 src/libcharon/plugins/xauth_eap/xauth_eap.c create mode 100644 src/libcharon/plugins/xauth_eap/xauth_eap.h create mode 100644 src/libcharon/plugins/xauth_eap/xauth_eap_plugin.c create mode 100644 src/libcharon/plugins/xauth_eap/xauth_eap_plugin.h diff --git a/configure.in b/configure.in index 417e33794..1d28cfac2 100755 --- a/configure.in +++ b/configure.in @@ -130,6 +130,7 @@ ARG_ENABL_SET([eap-peap], [enable EAP PEAP authentication module.]) ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.]) ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.]) ARG_ENABL_SET([xauth-generic], [enable generic XAuth backend.]) +ARG_ENABL_SET([xauth-eap], [enable XAuth backend using EAP methods to verify passwords.]) ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module.]) ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.]) ARG_ENABL_SET([tnc-imv], [enable TNC IMV module.]) @@ -845,6 +846,7 @@ ADD_PLUGIN([eap-ttls], [c libcharon]) ADD_PLUGIN([eap-peap], [c libcharon]) ADD_PLUGIN([eap-tnc], [c libcharon]) ADD_PLUGIN([xauth-generic], [c libcharon]) +ADD_PLUGIN([xauth-eap], [c libcharon]) ADD_PLUGIN([tnc-ifmap], [c libcharon]) ADD_PLUGIN([tnc-imc], [c libcharon]) ADD_PLUGIN([tnc-imv], [c libcharon]) @@ -965,6 +967,7 @@ AM_CONDITIONAL(USE_EAP_PEAP, test x$eap_peap = xtrue) AM_CONDITIONAL(USE_EAP_TNC, test x$eap_tnc = xtrue) AM_CONDITIONAL(USE_EAP_RADIUS, test x$eap_radius = xtrue) AM_CONDITIONAL(USE_XAUTH_GENERIC, test x$xauth_generic = xtrue) +AM_CONDITIONAL(USE_XAUTH_EAP, test x$xauth_eap = xtrue) AM_CONDITIONAL(USE_TNC_IFMAP, test x$tnc_ifmap = xtrue) AM_CONDITIONAL(USE_TNC_IMC, test x$tnc_imc = xtrue) AM_CONDITIONAL(USE_TNC_IMV, test x$tnc_imv = xtrue) @@ -1148,6 +1151,7 @@ AC_OUTPUT( src/libcharon/plugins/eap_tnc/Makefile src/libcharon/plugins/eap_radius/Makefile src/libcharon/plugins/xauth_generic/Makefile + src/libcharon/plugins/xauth_eap/Makefile src/libcharon/plugins/tnc_ifmap/Makefile src/libcharon/plugins/tnc_imc/Makefile src/libcharon/plugins/tnc_imv/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index a6334e1a0..8db43f188 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -524,3 +524,9 @@ if MONOLITHIC endif endif +if USE_XAUTH_EAP + SUBDIRS += plugins/xauth_eap +if MONOLITHIC + libcharon_la_LIBADD += plugins/xauth_eap/libstrongswan-xauth-eap.la +endif +endif 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..e59084344 --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap.c @@ -0,0 +1,284 @@ +/* + * 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_eap.h" + +#include + +#include +#include + +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; + } + + 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..655e057e7 --- /dev/null +++ b/src/libcharon/plugins/xauth_eap/xauth_eap.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +/** + * @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 + +/** + * XAuth methods that verifies XAuth credentials using EAP methods. + */ +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 . + * + * 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 + +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 . + * + * 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 + +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_ @}*/