<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<meta charset="utf-8">
Hello,<br>
the following patch is a small improvement for the xauth_pam plugin.<br>
The actual plugin performs the XAuth users authentication though PAM
but don't open/close the user sessions with the PAM
pam_open_session/pam_close_session methods.<br>
Just as comparison, opening/closing the PAM session is the behavior
of L2TP (strongswan -> xl2tpd -> pppd -> pam).<br>
Cheers,<br>
Andrea<br>
<br>
Signed-Off-By: Andrea Bonomi <a.bonomi at endian.com><br>
---<br>
src/libcharon/plugins/xauth_pam/Makefile.am | 3 +-<br>
.../plugins/xauth_pam/xauth_pam_listener.c | 156
++++++++++++++++++++<br>
.../plugins/xauth_pam/xauth_pam_listener.h | 50 +++++++<br>
src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c | 60 ++++++--<br>
4 files changed, 258 insertions(+), 11 deletions(-)<br>
<br>
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am
b/src/libcharon/plugins/xauth_pam/Makefile.am<br>
index a7d4f64..370661b 100644<br>
--- a/src/libcharon/plugins/xauth_pam/Makefile.am<br>
+++ b/src/libcharon/plugins/xauth_pam/Makefile.am<br>
@@ -14,6 +14,7 @@ endif<br>
<br>
libstrongswan_xauth_pam_la_SOURCES = \<br>
xauth_pam_plugin.h xauth_pam_plugin.c \<br>
- xauth_pam.h xauth_pam.c<br>
+ xauth_pam.h xauth_pam.c \<br>
+ xauth_pam_listener.h xauth_pam_listener.c<br>
<br>
libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam<br>
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c
b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c<br>
new file mode 100644<br>
index 0000000..236f6fa<br>
--- /dev/null<br>
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.c<br>
@@ -0,0 +1,156 @@<br>
+/*<br>
+ * Copyright (C) 2013 Endian srl<br>
+ * Author: Andrea Bonomi - <a class="moz-txt-link-rfc2396E" href="mailto:a.bonomi@endian.com"><a.bonomi@endian.com></a><br>
+ *<br>
+ * This program is free software; you can redistribute it and/or
modify it<br>
+ * under the terms of the GNU General Public License as published
by the<br>
+ * Free Software Foundation; either version 2 of the License, or
(at your<br>
+ * option) any later version. See
<a class="moz-txt-link-rfc2396E" href="http://www.fsf.org/copyleft/gpl.txt"><http://www.fsf.org/copyleft/gpl.txt></a>.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,
but<br>
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY<br>
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License<br>
+ * for more details.<br>
+ */<br>
+<br>
+#define _GNU_SOURCE<br>
+#include <stdio.h><br>
+<br>
+#include "xauth_pam_listener.h"<br>
+<br>
+#include <daemon.h><br>
+#include <library.h><br>
+<br>
+#include <security/pam_appl.h><br>
+<br>
+typedef struct private_xauth_pam_listener_t
private_xauth_pam_listener_t;<br>
+<br>
+/**<br>
+ * Private data of an xauth_pam_listener_t object.<br>
+ */<br>
+struct private_xauth_pam_listener_t {<br>
+<br>
+ /**<br>
+ * Public xauth_pam_listener_t interface.<br>
+ */<br>
+ xauth_pam_listener_t public;<br>
+<br>
+};<br>
+<br>
+static struct pam_conv null_conv = {<br>
+ NULL<br>
+};<br>
+<br>
+static void open_close_session(private_xauth_pam_listener_t *this,
ike_sa_t *ike_sa, bool up)<br>
+{<br>
+ pam_handle_t *pamh = NULL;<br>
+ char *user = NULL;<br>
+ char *service = NULL;<br>
+ int ret;<br>
+ enumerator_t *enumerator;<br>
+ host_t *vip;<br>
+<br>
+ /* Look for PAM service, with a legacy fallback for the eap-gtc
plugin.<br>
+ * Default to "login". */<br>
+ service = lib->settings->get_str(lib->settings,<br>
+ "%s.plugins.xauth-pam.pam_service",<br>
+ lib->settings->get_str(lib->settings,<br>
+ "%s.plugins.eap-gtc.pam_service",<br>
+ "login", charon->name),<br>
+ charon->name);<br>
+<br>
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa,
FALSE);<br>
+ while (enumerator->enumerate(enumerator, &vip))<br>
+ {<br>
+ if (asprintf(&user, "%Y",
ike_sa->get_other_eap_id(ike_sa)) == -1)<br>
+ {<br>
+ user = NULL;<br>
+ continue;<br>
+ }<br>
+ ret = pam_start(service, user, &null_conv, &pamh);<br>
+<br>
+ if (ret != PAM_SUCCESS)<br>
+ {<br>
+ DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",<br>
+ user, pam_strerror(pamh, ret));<br>
+ }<br>
+ else if (up)<br>
+ {<br>
+ ret = pam_open_session(pamh, 0);<br>
+ if (ret != PAM_SUCCESS)<br>
+ {<br>
+ DBG1(DBG_IKE, "XAuth pam_open_session for '%s'
failed: %s",<br>
+ user, pam_strerror(pamh, ret));<br>
+ }<br>
+ }<br>
+ else<br>
+ {<br>
+ ret = pam_close_session(pamh, 0);<br>
+ if (ret != PAM_SUCCESS)<br>
+ {<br>
+ DBG1(DBG_IKE, "XAuth pam_close_session for '%s'
failed: %s",<br>
+ user, pam_strerror(pamh, ret));<br>
+ }<br>
+ }<br>
+ pam_end(pamh, ret);<br>
+ free(user);<br>
+ }<br>
+ enumerator->destroy(enumerator);<br>
+<br>
+ return TRUE;<br>
+}<br>
+<br>
+METHOD(listener_t, message_hook, bool,<br>
+ private_xauth_pam_listener_t *this, ike_sa_t *ike_sa,<br>
+ message_t *message, bool incoming, bool plain)<br>
+{<br>
+ if (plain && ike_sa->get_state(ike_sa) ==
IKE_ESTABLISHED &&<br>
+ !incoming && !message->get_request(message))<br>
+ {<br>
+ if (ike_sa->get_version(ike_sa) == IKEV1 &&<br>
+ message->get_exchange_type(message) == TRANSACTION)<br>
+ {<br>
+ open_close_session(this, ike_sa, TRUE);<br>
+ }<br>
+ if (ike_sa->get_version(ike_sa) == IKEV2 &&<br>
+ message->get_exchange_type(message) == IKE_AUTH)<br>
+ {<br>
+ open_close_session(this, ike_sa, TRUE);<br>
+ }<br>
+ }<br>
+ return TRUE;<br>
+}<br>
+<br>
+METHOD(listener_t, ike_updown, bool,<br>
+ private_xauth_pam_listener_t *this, ike_sa_t *ike_sa, bool up)<br>
+{<br>
+ if (!up)<br>
+ {<br>
+ open_close_session(this, ike_sa, FALSE);<br>
+ }<br>
+ return TRUE;<br>
+}<br>
+<br>
+METHOD(xauth_pam_listener_t, listener_destroy, void,<br>
+ private_xauth_pam_listener_t *this)<br>
+{<br>
+ free(this);<br>
+}<br>
+<br>
+xauth_pam_listener_t *xauth_pam_listener_create()<br>
+{<br>
+ private_xauth_pam_listener_t *this;<br>
+<br>
+ INIT(this,<br>
+ .public = {<br>
+ .listener = {<br>
+ .message = _message_hook,<br>
+ .ike_updown = _ike_updown,<br>
+ },<br>
+ .destroy = _listener_destroy,<br>
+ },<br>
+ );<br>
+<br>
+ return &this->public;<br>
+}<br>
+<br>
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h<br>
new file mode 100644<br>
index 0000000..6e25966<br>
--- /dev/null<br>
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h<br>
@@ -0,0 +1,50 @@<br>
+/*<br>
+ * Copyright (C) 2013 Endian srl<br>
+ * Author: Andrea Bonomi <a class="moz-txt-link-rfc2396E" href="mailto:a.bonomi@endian.com"><a.bonomi@endian.com></a><br>
+ *<br>
+ * This program is free software; you can redistribute it and/or
modify it<br>
+ * under the terms of the GNU General Public License as published
by the<br>
+ * Free Software Foundation; either version 2 of the License, or
(at your<br>
+ * option) any later version. See
<a class="moz-txt-link-rfc2396E" href="http://www.fsf.org/copyleft/gpl.txt"><http://www.fsf.org/copyleft/gpl.txt></a>.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,
but<br>
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY<br>
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License<br>
+ * for more details.<br>
+ */<br>
+<br>
+/**<br>
+ * @defgroup xauth_pam_i xauth_pam<br>
+ * @{ @ingroup xauth_pam<br>
+ */<br>
+<br>
+#ifndef XAUTH_PAM_LISENER_H_<br>
+#define XAUTH_PAM_LISTENER_H_<br>
+<br>
+typedef struct xauth_pam_listener_t xauth_pam_listener_t;<br>
+<br>
+#include <bus/listeners/listener.h><br>
+<br>
+/**<br>
+ * Listener<br>
+ */<br>
+struct xauth_pam_listener_t {<br>
+<br>
+ /**<br>
+ * Implements listener_t interface.<br>
+ */<br>
+ listener_t listener;<br>
+<br>
+ /**<br>
+ * Destroy a xauth_pam_listener_t.<br>
+ */<br>
+ void (*destroy)(xauth_pam_listener_t *this);<br>
+};<br>
+<br>
+/**<br>
+ * Create a xauth_pam_listener instance.<br>
+ */<br>
+xauth_pam_listener_t *xauth_pam_listener_create();<br>
+<br>
+<br>
+#endif /** XAUTH_PAM_LISTENER_H_ @}*/<br>
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
index 2ef9a6c..6e13c0b 100644<br>
--- a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c<br>
@@ -15,6 +15,7 @@<br>
<br>
#include "xauth_pam_plugin.h"<br>
#include "xauth_pam.h"<br>
+#include "xauth_pam_listener.h"<br>
<br>
#include <daemon.h><br>
<br>
@@ -22,17 +23,53 @@<br>
#define CAP_AUDIT_WRITE 29<br>
#endif<br>
<br>
+typedef struct private_xauth_pam_plugin_t
private_xauth_pam_plugin_t;<br>
+<br>
+/**<br>
+ * private data of xauth_pam plugin<br>
+ */<br>
+struct private_xauth_pam_plugin_t {<br>
+<br>
+ /**<br>
+ * implements plugin interface<br>
+ */<br>
+ xauth_pam_plugin_t public;<br>
+<br>
+ /**<br>
+ * Listener <br>
+ */<br>
+ xauth_pam_listener_t *listener;<br>
+<br>
+};<br>
+<br>
+bool xauth_pam_method_register(private_xauth_pam_plugin_t *this,
plugin_feature_t *feature,<br>
+ bool reg, void *data)<br>
+{<br>
+ /* (un-)register XAuth methods from plugin features */<br>
+ xauth_method_register(this, feature, reg, data);<br>
+ if (reg)<br>
+ {<br>
+ charon->bus->add_listener(charon->bus,
&this->listener->listener);<br>
+ }<br>
+ else<br>
+ {<br>
+ charon->bus->remove_listener(charon->bus,
&this->listener->listener);<br>
+ }<br>
+ return TRUE;<br>
+}<br>
+<br>
+<br>
METHOD(plugin_t, get_name, char*,<br>
- xauth_pam_plugin_t *this)<br>
+ private_xauth_pam_plugin_t *this)<br>
{<br>
return "xauth-pam";<br>
}<br>
<br>
METHOD(plugin_t, get_features, int,<br>
- xauth_pam_plugin_t *this, plugin_feature_t *features[])<br>
+ private_xauth_pam_plugin_t *this, plugin_feature_t *features[])<br>
{<br>
static plugin_feature_t f[] = {<br>
- PLUGIN_CALLBACK(xauth_method_register,
xauth_pam_create_server),<br>
+ PLUGIN_CALLBACK(xauth_pam_method_register,
xauth_pam_create_server),<br>
PLUGIN_PROVIDE(XAUTH_SERVER, "pam"),<br>
};<br>
*features = f;<br>
@@ -40,7 +77,7 @@ METHOD(plugin_t, get_features, int,<br>
}<br>
<br>
METHOD(plugin_t, destroy, void,<br>
- xauth_pam_plugin_t *this)<br>
+ private_xauth_pam_plugin_t *this)<br>
{<br>
free(this);<br>
}<br>
@@ -50,7 +87,7 @@ METHOD(plugin_t, destroy, void,<br>
*/<br>
plugin_t *xauth_pam_plugin_create()<br>
{<br>
- xauth_pam_plugin_t *this;<br>
+ private_xauth_pam_plugin_t *this;<br>
<br>
/* required for PAM authentication */<br>
if (!lib->caps->keep(lib->caps, CAP_AUDIT_WRITE))<br>
@@ -60,12 +97,15 @@ plugin_t *xauth_pam_plugin_create()<br>
}<br>
<br>
INIT(this,<br>
- .plugin = {<br>
- .get_name = _get_name,<br>
- .get_features = _get_features,<br>
- .destroy = _destroy,<br>
+ .public = {<br>
+ .plugin = {<br>
+ .get_name = _get_name,<br>
+ .get_features = _get_features,<br>
+ .destroy = _destroy,<br>
+ },<br>
},<br>
+ .listener = xauth_pam_listener_create(),<br>
);<br>
<br>
- return &this->plugin;<br>
+ return &this->public.plugin;<br>
}<br>
<br>
</body>
</html>