Add xauth-pam, an XAuth backend verifying credentials with PAM
parent
0bac49b0a9
commit
b9e4916321
|
@ -134,6 +134,7 @@ ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.]
|
|||
ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.])
|
||||
ARG_DISBL_SET([xauth-generic], [disable generic XAuth backend.])
|
||||
ARG_ENABL_SET([xauth-eap], [enable XAuth backend using EAP methods to verify passwords.])
|
||||
ARG_ENABL_SET([xauth-pam], [enable XAuth backend using PAM to verify passwords.])
|
||||
ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module.])
|
||||
ARG_ENABL_SET([tnc-pdp], [enable TNC policy decision point module.])
|
||||
ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.])
|
||||
|
@ -745,7 +746,7 @@ if test x$nm = xtrue; then
|
|||
AC_SUBST(nm_LIBS)
|
||||
fi
|
||||
|
||||
if test x$eap_gtc = xtrue; then
|
||||
if test x$xauth_pam = xtrue; then
|
||||
AC_HAVE_LIBRARY([pam],[LIBS="$LIBS"],[AC_MSG_ERROR([PAM library not found])])
|
||||
AC_CHECK_HEADER([security/pam_appl.h],,[AC_MSG_ERROR([PAM header security/pam_appl.h not found!])])
|
||||
fi
|
||||
|
@ -900,6 +901,7 @@ ADD_PLUGIN([eap-peap], [c charon nm])
|
|||
ADD_PLUGIN([eap-tnc], [c charon])
|
||||
ADD_PLUGIN([xauth-generic], [c charon])
|
||||
ADD_PLUGIN([xauth-eap], [c charon])
|
||||
ADD_PLUGIN([xauth-pam], [c charon])
|
||||
ADD_PLUGIN([tnc-ifmap], [c charon])
|
||||
ADD_PLUGIN([tnc-pdp], [c charon])
|
||||
ADD_PLUGIN([tnc-imc], [c charon])
|
||||
|
@ -1026,6 +1028,7 @@ 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_XAUTH_PAM, test x$xauth_pam = xtrue)
|
||||
AM_CONDITIONAL(USE_TNC_IFMAP, test x$tnc_ifmap = xtrue)
|
||||
AM_CONDITIONAL(USE_TNC_PDP, test x$tnc_pdp = xtrue)
|
||||
AM_CONDITIONAL(USE_TNC_IMC, test x$tnc_imc = xtrue)
|
||||
|
@ -1204,6 +1207,7 @@ AC_OUTPUT(
|
|||
src/libcharon/plugins/eap_radius/Makefile
|
||||
src/libcharon/plugins/xauth_generic/Makefile
|
||||
src/libcharon/plugins/xauth_eap/Makefile
|
||||
src/libcharon/plugins/xauth_pam/Makefile
|
||||
src/libcharon/plugins/tnc_ifmap/Makefile
|
||||
src/libcharon/plugins/tnc_pdp/Makefile
|
||||
src/libcharon/plugins/tnc_imc/Makefile
|
||||
|
|
|
@ -546,3 +546,10 @@ if MONOLITHIC
|
|||
libcharon_la_LIBADD += plugins/xauth_eap/libstrongswan-xauth-eap.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_XAUTH_PAM
|
||||
SUBDIRS += plugins/xauth_pam
|
||||
if MONOLITHIC
|
||||
libcharon_la_LIBADD += plugins/xauth_pam/libstrongswan-xauth-pam.la
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -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-pam.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-xauth-pam.la
|
||||
endif
|
||||
|
||||
libstrongswan_xauth_pam_la_SOURCES = \
|
||||
xauth_pam_plugin.h xauth_pam_plugin.c \
|
||||
xauth_pam.h xauth_pam.c
|
||||
|
||||
libstrongswan_xauth_pam_la_LDFLAGS = -module -avoid-version -lpam
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Martin Willi
|
||||
* Copyright (C) 2012 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_pam.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <library.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
typedef struct private_xauth_pam_t private_xauth_pam_t;
|
||||
|
||||
/**
|
||||
* Private data of an xauth_pam_t object.
|
||||
*/
|
||||
struct private_xauth_pam_t {
|
||||
|
||||
/**
|
||||
* Public interface.
|
||||
*/
|
||||
xauth_pam_t public;
|
||||
|
||||
/**
|
||||
* ID of the peer
|
||||
*/
|
||||
identification_t *peer;
|
||||
};
|
||||
|
||||
METHOD(xauth_method_t, initiate, status_t,
|
||||
private_xauth_pam_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* PAM conv callback function
|
||||
*/
|
||||
static int auth_conv(int num_msg, const struct pam_message **msg,
|
||||
struct pam_response **resp, char *password)
|
||||
{
|
||||
struct pam_response *response;
|
||||
|
||||
if (num_msg != 1)
|
||||
{
|
||||
return PAM_CONV_ERR;
|
||||
}
|
||||
response = malloc(sizeof(struct pam_response));
|
||||
response->resp = strdup(password);
|
||||
response->resp_retcode = 0;
|
||||
*resp = response;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a username/password using PAM
|
||||
*/
|
||||
static bool authenticate(char *service, char *user, char *password)
|
||||
{
|
||||
pam_handle_t *pamh = NULL;
|
||||
static struct pam_conv conv;
|
||||
int ret;
|
||||
|
||||
conv.conv = (void*)auth_conv;
|
||||
conv.appdata_ptr = password;
|
||||
|
||||
ret = pam_start(service, user, &conv, &pamh);
|
||||
if (ret != PAM_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",
|
||||
user, pam_strerror(pamh, ret));
|
||||
return FALSE;
|
||||
}
|
||||
ret = pam_authenticate(pamh, 0);
|
||||
if (ret == PAM_SUCCESS)
|
||||
{
|
||||
ret = pam_acct_mgmt(pamh, 0);
|
||||
if (ret != PAM_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "XAuth pam_acct_mgmt for '%s' failed: %s",
|
||||
user, pam_strerror(pamh, ret));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IKE, "XAuth pam_authenticate for '%s' failed: %s",
|
||||
user, pam_strerror(pamh, ret));
|
||||
}
|
||||
pam_end(pamh, ret);
|
||||
return ret == PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert configuration attribute content to a null-terminated string
|
||||
*/
|
||||
static void attr2string(char *buf, size_t len, chunk_t chunk)
|
||||
{
|
||||
if (chunk.len && chunk.len < len)
|
||||
{
|
||||
snprintf(buf, len, "%.*s", (int)chunk.len, chunk.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, process, status_t,
|
||||
private_xauth_pam_t *this, cp_payload_t *in, cp_payload_t **out)
|
||||
{
|
||||
char *service, user[128] = "", pass[128] = "", *pos;
|
||||
configuration_attribute_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
chunk_t chunk;
|
||||
|
||||
enumerator = in->create_attribute_enumerator(in);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
switch (attr->get_type(attr))
|
||||
{
|
||||
case XAUTH_USER_NAME:
|
||||
/* trim to username part if email address given */
|
||||
chunk = attr->get_chunk(attr);
|
||||
pos = memchr(chunk.ptr, '@', chunk.len);
|
||||
if (pos)
|
||||
{
|
||||
chunk.len = (u_char*)pos - chunk.ptr;
|
||||
}
|
||||
attr2string(user, sizeof(user), chunk);
|
||||
break;
|
||||
case XAUTH_USER_PASSWORD:
|
||||
attr2string(pass, sizeof(pass), attr->get_chunk(attr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!user[0] || !pass[0])
|
||||
{
|
||||
DBG1(DBG_IKE, "peer did not respond to our XAuth request");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
this->peer->destroy(this->peer);
|
||||
this->peer = identification_create_from_string(user);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (authenticate(service, user, pass))
|
||||
{
|
||||
DBG1(DBG_IKE, "PAM authentication of '%s' successful", user);
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, get_identity, identification_t*,
|
||||
private_xauth_pam_t *this)
|
||||
{
|
||||
return this->peer;
|
||||
}
|
||||
|
||||
METHOD(xauth_method_t, destroy, void,
|
||||
private_xauth_pam_t *this)
|
||||
{
|
||||
this->peer->destroy(this->peer);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
xauth_pam_t *xauth_pam_create_server(identification_t *server,
|
||||
identification_t *peer)
|
||||
{
|
||||
private_xauth_pam_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.xauth_method = {
|
||||
.initiate = _initiate,
|
||||
.process = _process,
|
||||
.get_identity = _get_identity,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.peer = peer->clone(peer),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Martin Willi
|
||||
* Copyright (C) 2012 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_pam_i xauth_pam
|
||||
* @{ @ingroup xauth_pam
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_PAM_H_
|
||||
#define XAUTH_PAM_H_
|
||||
|
||||
typedef struct xauth_pam_t xauth_pam_t;
|
||||
|
||||
#include <sa/xauth/xauth_method.h>
|
||||
|
||||
/**
|
||||
* XAuth plugin using Pluggable Authentication Modules to verify credentials.
|
||||
*/
|
||||
struct xauth_pam_t {
|
||||
|
||||
/**
|
||||
* Implemented xauth_method_t interface.
|
||||
*/
|
||||
xauth_method_t xauth_method;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the XAuth method using PAM, acting as server.
|
||||
*
|
||||
* @param server ID of the XAuth server
|
||||
* @param peer ID of the XAuth client
|
||||
* @return xauth_pam_t object
|
||||
*/
|
||||
xauth_pam_t *xauth_pam_create_server(identification_t *server,
|
||||
identification_t *peer);
|
||||
|
||||
#endif /** XAUTH_PAM_H_ @}*/
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Martin Willi
|
||||
* Copyright (C) 2012 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_pam_plugin.h"
|
||||
#include "xauth_pam.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
xauth_pam_plugin_t *this)
|
||||
{
|
||||
return "xauth-pam";
|
||||
}
|
||||
|
||||
METHOD(plugin_t, get_features, int,
|
||||
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"),
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
}
|
||||
|
||||
METHOD(plugin_t, destroy, void,
|
||||
xauth_pam_plugin_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
plugin_t *xauth_pam_plugin_create()
|
||||
{
|
||||
xauth_pam_plugin_t *this;
|
||||
|
||||
INIT(this,
|
||||
.plugin = {
|
||||
.get_name = _get_name,
|
||||
.get_features = _get_features,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
return &this->plugin;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Martin Willi
|
||||
* Copyright (C) 2012 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_pam xauth_pam
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup xauth_pam_plugin xauth_pam_plugin
|
||||
* @{ @ingroup xauth_pam
|
||||
*/
|
||||
|
||||
#ifndef XAUTH_PAM_PLUGIN_H_
|
||||
#define XAUTH_PAM_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct xauth_pam_plugin_t xauth_pam_plugin_t;
|
||||
|
||||
/**
|
||||
* XAuth plugin using Pluggable Authentication Modules to verify credentials.
|
||||
*/
|
||||
struct xauth_pam_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
#endif /** XAUTH_PAM_PLUGIN_H_ @}*/
|
Loading…
Reference in New Issue