From 2312504d1ef5001277da1df66787df0ffeddfb40 Mon Sep 17 00:00:00 2001 From: Andrea Bonomi Date: Tue, 21 Jan 2014 09:54:20 +0100 Subject: [PATCH] xauth-pam: Open/close a PAM session for each connected client Signed-off-by: Andrea Bonomi --- src/libcharon/plugins/xauth_pam/Makefile.am | 1 + .../plugins/xauth_pam/xauth_pam_listener.c | 144 ++++++++++++++++++ .../plugins/xauth_pam/xauth_pam_listener.h | 58 +++++++ .../plugins/xauth_pam/xauth_pam_plugin.c | 71 +++++++-- 4 files changed, 265 insertions(+), 9 deletions(-) create mode 100644 src/libcharon/plugins/xauth_pam/xauth_pam_listener.c create mode 100644 src/libcharon/plugins/xauth_pam/xauth_pam_listener.h diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am index a7d4f6436a..1875f81d33 100644 --- a/src/libcharon/plugins/xauth_pam/Makefile.am +++ b/src/libcharon/plugins/xauth_pam/Makefile.am @@ -14,6 +14,7 @@ endif libstrongswan_xauth_pam_la_SOURCES = \ xauth_pam_plugin.h xauth_pam_plugin.c \ + xauth_pam_listener.h xauth_pam_listener.c \ xauth_pam.h xauth_pam.c libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c new file mode 100644 index 0000000000..1b9c045c72 --- /dev/null +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2013 Endian srl + * Author: Andrea Bonomi - + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define _GNU_SOURCE +#include + +#include "xauth_pam_listener.h" + +#include +#include + +#include + +typedef struct private_xauth_pam_listener_t private_xauth_pam_listener_t; + +/** + * Private data of an xauth_pam_listener_t object. + */ +struct private_xauth_pam_listener_t { + + /** + * Public xauth_pam_listener_t interface. + */ + xauth_pam_listener_t public; + + /** + * PAM service + */ + char *service; +}; + +/** + * PAM conv callback function + */ +static int conv(int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *data) +{ + int i; + + for (i = 0; i < num_msg; i++) + { + /* ignore any text info, but fail on any interaction request */ + if (msg[i]->msg_style != PAM_TEXT_INFO) + { + return PAM_CONV_ERR; + } + } + return PAM_SUCCESS; +} + +METHOD(listener_t, ike_updown, bool, + private_xauth_pam_listener_t *this, ike_sa_t *ike_sa, bool up) +{ + struct pam_conv null_conv = { + .conv = conv, + }; + pam_handle_t *pamh = NULL; + char *user; + int ret; + + if (asprintf(&user, "%Y", ike_sa->get_other_eap_id(ike_sa)) != -1) + { + ret = pam_start(this->service, user, &null_conv, &pamh); + if (ret == PAM_SUCCESS) + { + if (up) + { + ret = pam_open_session(pamh, 0); + if (ret != PAM_SUCCESS) + { + DBG1(DBG_IKE, "XAuth pam_open_session for '%s' failed: %s", + user, pam_strerror(pamh, ret)); + } + } + else + { + ret = pam_close_session(pamh, 0); + if (ret != PAM_SUCCESS) + { + DBG1(DBG_IKE, "XAuth pam_close_session for '%s' failed: %s", + user, pam_strerror(pamh, ret)); + } + } + } + else + { + DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s", + user, pam_strerror(pamh, ret)); + } + pam_end(pamh, ret); + free(user); + } + return TRUE; +} + +METHOD(xauth_pam_listener_t, listener_destroy, void, + private_xauth_pam_listener_t *this) +{ + free(this); +} + +xauth_pam_listener_t *xauth_pam_listener_create() +{ + private_xauth_pam_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_updown = _ike_updown, + }, + .destroy = _listener_destroy, + }, + /* Look for PAM service, with a legacy fallback for the eap-gtc plugin. + * Default to "login". */ + .service = lib->settings->get_str(lib->settings, + "%s.plugins.xauth-pam.pam_service", + lib->settings->get_str(lib->settings, + "%s.plugins.eap-gtc.pam_service", + "login", charon->name), + charon->name), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h new file mode 100644 index 0000000000..5b15410f44 --- /dev/null +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 Endian srl + * Author: Andrea Bonomi - + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup xauth_pam_i xauth_pam + * @{ @ingroup xauth_pam + */ + +#ifndef XAUTH_PAM_LISENER_H_ +#define XAUTH_PAM_LISTENER_H_ + +typedef struct xauth_pam_listener_t xauth_pam_listener_t; + +#include + +/** + * Listener + */ +struct xauth_pam_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a xauth_pam_listener_t. + */ + void (*destroy)(xauth_pam_listener_t *this); +}; + +/** + * Create a xauth_pam_listener instance. + */ +xauth_pam_listener_t *xauth_pam_listener_create(); + + +#endif /** XAUTH_PAM_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c index 2ef9a6c8f9..f70f30ef3f 100644 --- a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c +++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c @@ -15,6 +15,7 @@ #include "xauth_pam_plugin.h" #include "xauth_pam.h" +#include "xauth_pam_listener.h" #include @@ -22,26 +23,73 @@ #define CAP_AUDIT_WRITE 29 #endif +typedef struct private_xauth_pam_plugin_t private_xauth_pam_plugin_t; + +/** + * private data of xauth_pam plugin + */ +struct private_xauth_pam_plugin_t { + + /** + * implements plugin interface + */ + xauth_pam_plugin_t public; + + /** + * Listener + */ + xauth_pam_listener_t *listener; + + /** + * Do PAM session management? + */ + bool session; +}; + +/** + * Register XAuth method and listener + */ +static bool register_listener(private_xauth_pam_plugin_t *this, + plugin_feature_t *feature, bool reg, void *data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + METHOD(plugin_t, get_name, char*, - xauth_pam_plugin_t *this) + private_xauth_pam_plugin_t *this) { return "xauth-pam"; } METHOD(plugin_t, get_features, int, - xauth_pam_plugin_t *this, plugin_feature_t *features[]) + private_xauth_pam_plugin_t *this, plugin_feature_t *features[]) { static plugin_feature_t f[] = { PLUGIN_CALLBACK(xauth_method_register, xauth_pam_create_server), PLUGIN_PROVIDE(XAUTH_SERVER, "pam"), + PLUGIN_CALLBACK((plugin_feature_callback_t)register_listener, NULL), + PLUGIN_PROVIDE(CUSTOM, "pam-session"), }; *features = f; + if (!this->session) + { + return 2; + } return countof(f); } METHOD(plugin_t, destroy, void, - xauth_pam_plugin_t *this) + private_xauth_pam_plugin_t *this) { + this->listener->destroy(this->listener), free(this); } @@ -50,7 +98,7 @@ METHOD(plugin_t, destroy, void, */ plugin_t *xauth_pam_plugin_create() { - xauth_pam_plugin_t *this; + private_xauth_pam_plugin_t *this; /* required for PAM authentication */ if (!lib->caps->keep(lib->caps, CAP_AUDIT_WRITE)) @@ -60,12 +108,17 @@ plugin_t *xauth_pam_plugin_create() } INIT(this, - .plugin = { - .get_name = _get_name, - .get_features = _get_features, - .destroy = _destroy, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, }, + .session = lib->settings->get_str(lib->settings, + "%s.plugins.xauth-pam.session", FALSE, charon->name), + .listener = xauth_pam_listener_create(), ); - return &this->plugin; + return &this->public.plugin; } -- 2.47.2