Merge branch 'pam-session'

Add support for PAM session management in xauth-pam.
This commit is contained in:
Martin Willi
2014-01-23 16:14:46 +01:00
7 changed files with 276 additions and 10 deletions
+3
View File
@@ -11,6 +11,9 @@ strongswan-5.1.2
- Defined a TPMRA remote attestation workitem and added support for it to the - Defined a TPMRA remote attestation workitem and added support for it to the
Attestation IMV. Attestation IMV.
- When enabling its "session" strongswan.conf option, the xauth-pam plugin opens
and closes a PAM session for each established IKE_SA. Patch courtesy of
Andrea Bonomi.
strongswan-5.1.1 strongswan-5.1.1
---------------- ----------------
+3
View File
@@ -804,6 +804,9 @@ EAP plugin to be used as backend for XAuth credential verification
.BR charon.plugins.xauth-pam.pam_service " [login]" .BR charon.plugins.xauth-pam.pam_service " [login]"
PAM service to be used for authentication PAM service to be used for authentication
.TP .TP
.BR charon.plugins.xauth-pam.session " [no]"
Open/close a PAM session for each active IKE_SA
.TP
.BR charon.plugins.xauth-pam.trim_email " [yes]" .BR charon.plugins.xauth-pam.trim_email " [yes]"
If an email address is given as an XAuth username, trim it to just the If an email address is given as an XAuth username, trim it to just the
username part. username part.
@@ -14,6 +14,7 @@ endif
libstrongswan_xauth_pam_la_SOURCES = \ libstrongswan_xauth_pam_la_SOURCES = \
xauth_pam_plugin.h xauth_pam_plugin.c \ xauth_pam_plugin.h xauth_pam_plugin.c \
xauth_pam_listener.h xauth_pam_listener.c \
xauth_pam.h xauth_pam.c xauth_pam.h xauth_pam.c
libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam
+5 -1
View File
@@ -116,7 +116,11 @@ static void attr2string(char *buf, size_t len, chunk_t chunk)
{ {
if (chunk.len && chunk.len < len) if (chunk.len && chunk.len < len)
{ {
snprintf(buf, len, "%.*s", (int)chunk.len, chunk.ptr); chunk_t sane;
chunk_printable(chunk, &sane, '?');
snprintf(buf, len, "%.*s", (int)sane.len, sane.ptr);
chunk_clear(&sane);
} }
} }
@@ -0,0 +1,144 @@
/*
* Copyright (C) 2013 Endian srl
* Author: Andrea Bonomi - <[email protected]>
*
* 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 <stdio.h>
#include "xauth_pam_listener.h"
#include <daemon.h>
#include <library.h>
#include <security/pam_appl.h>
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;
}
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2013 Endian srl
* Author: Andrea Bonomi - <[email protected]>
*
* 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 <bus/listeners/listener.h>
/**
* 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_ @}*/
@@ -15,6 +15,7 @@
#include "xauth_pam_plugin.h" #include "xauth_pam_plugin.h"
#include "xauth_pam.h" #include "xauth_pam.h"
#include "xauth_pam_listener.h"
#include <daemon.h> #include <daemon.h>
@@ -22,26 +23,73 @@
#define CAP_AUDIT_WRITE 29 #define CAP_AUDIT_WRITE 29
#endif #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*, METHOD(plugin_t, get_name, char*,
xauth_pam_plugin_t *this) private_xauth_pam_plugin_t *this)
{ {
return "xauth-pam"; return "xauth-pam";
} }
METHOD(plugin_t, get_features, int, 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[] = { static plugin_feature_t f[] = {
PLUGIN_CALLBACK(xauth_method_register, xauth_pam_create_server), PLUGIN_CALLBACK(xauth_method_register, xauth_pam_create_server),
PLUGIN_PROVIDE(XAUTH_SERVER, "pam"), PLUGIN_PROVIDE(XAUTH_SERVER, "pam"),
PLUGIN_CALLBACK((plugin_feature_callback_t)register_listener, NULL),
PLUGIN_PROVIDE(CUSTOM, "pam-session"),
}; };
*features = f; *features = f;
if (!this->session)
{
return 2;
}
return countof(f); return countof(f);
} }
METHOD(plugin_t, destroy, void, METHOD(plugin_t, destroy, void,
xauth_pam_plugin_t *this) private_xauth_pam_plugin_t *this)
{ {
this->listener->destroy(this->listener),
free(this); free(this);
} }
@@ -50,7 +98,7 @@ METHOD(plugin_t, destroy, void,
*/ */
plugin_t *xauth_pam_plugin_create() plugin_t *xauth_pam_plugin_create()
{ {
xauth_pam_plugin_t *this; private_xauth_pam_plugin_t *this;
/* required for PAM authentication */ /* required for PAM authentication */
if (!lib->caps->keep(lib->caps, CAP_AUDIT_WRITE)) if (!lib->caps->keep(lib->caps, CAP_AUDIT_WRITE))
@@ -60,12 +108,17 @@ plugin_t *xauth_pam_plugin_create()
} }
INIT(this, INIT(this,
.plugin = { .public = {
.get_name = _get_name, .plugin = {
.get_features = _get_features, .get_name = _get_name,
.destroy = _destroy, .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;
} }