aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2012-08-09 14:39:31 +0200
committerMartin Willi <martin@revosec.ch>2012-08-10 10:43:44 +0200
commitb9e491632133440ec14df4396f00a12b7c5b716c (patch)
treecd953559d9884c4412c05a6e345b00a9a4d82ca8
parent0bac49b0a95b54dbd382cfade94149fa0c4b95f4 (diff)
downloadstrongswan-b9e491632133440ec14df4396f00a12b7c5b716c.tar.bz2
strongswan-b9e491632133440ec14df4396f00a12b7c5b716c.tar.xz
Add xauth-pam, an XAuth backend verifying credentials with PAM
-rw-r--r--configure.in6
-rw-r--r--src/libcharon/Makefile.am7
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.am17
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam.c215
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam.h49
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c60
-rw-r--r--src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h42
7 files changed, 395 insertions, 1 deletions
diff --git a/configure.in b/configure.in
index c5fd1d3c6..a1adb8cc1 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index a254c0336..2d4227990 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -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
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am
new file mode 100644
index 000000000..47521a3ff
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/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-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
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.c b/src/libcharon/plugins/xauth_pam/xauth_pam.c
new file mode 100644
index 000000000..98c1a97a4
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.c
@@ -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;
+}
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.h b/src/libcharon/plugins/xauth_pam/xauth_pam.h
new file mode 100644
index 000000000..f2d310c0d
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.h
@@ -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_ @}*/
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
new file mode 100644
index 000000000..363aaf003
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
@@ -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;
+}
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
new file mode 100644
index 000000000..b75268880
--- /dev/null
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_plugin.h
@@ -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_ @}*/