aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/Makefile.am1
-rw-r--r--conf/plugins/ext-auth.opt15
-rw-r--r--configure.ac4
-rw-r--r--src/libcharon/Makefile.am7
-rw-r--r--src/libcharon/plugins/ext_auth/Makefile.am18
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_listener.c203
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_listener.h59
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_plugin.c156
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_plugin.h49
9 files changed, 512 insertions, 0 deletions
diff --git a/conf/Makefile.am b/conf/Makefile.am
index ee9ce72ea..e5077391a 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -45,6 +45,7 @@ plugins = \
plugins/eap-tnc.opt \
plugins/eap-ttls.opt \
plugins/error-notify.opt \
+ plugins/ext-auth.opt \
plugins/gcrypt.opt \
plugins/ha.opt \
plugins/imc-attestation.opt \
diff --git a/conf/plugins/ext-auth.opt b/conf/plugins/ext-auth.opt
new file mode 100644
index 000000000..bf127b9d7
--- /dev/null
+++ b/conf/plugins/ext-auth.opt
@@ -0,0 +1,15 @@
+charon.plugins.ext-auth.script =
+ Shell script to invoke for peer authorization.
+
+ Command to pass to the system shell for peer authorization. Authorization
+ is considered successful if the command executes normally with an exit code
+ of zero. For all other exit codes IKE_SA authorization is rejected.
+
+ The following environment variables get passed to the script:
+ _IKE_UNIQUE_ID_: The IKE_SA numerical unique identifier.
+ _IKE_NAME_: The peer configuration connection name.
+ _IKE_LOCAL_HOST_: Local IKE IP address.
+ _IKE_REMOTE_HOST_: Remote IKE IP address.
+ _IKE_LOCAL_ID_: Local IKE identity.
+ _IKE_REMOTE_ID_: Remote IKE identity.
+ _IKE_REMOTE_EAP_ID_: Remote EAP or XAuth identity, if used.
diff --git a/configure.ac b/configure.ac
index 85f7cb35c..100e29afc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,6 +189,7 @@ ARG_ENABL_SET([eap-peap], [enable EAP PEAP authentication module.])
ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.])
ARG_ENABL_SET([eap-dynamic], [enable dynamic EAP proxy module.])
ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.])
+ARG_ENABL_SET([ext-auth], [enable plugin calling an external authorization script.])
ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.])
ARG_ENABL_SET([keychain], [enables OS X Keychain Services credential set.])
ARG_ENABL_SET([pkcs11], [enables the PKCS11 token support plugin.])
@@ -1285,6 +1286,7 @@ ADD_PLUGIN([android-dns], [c charon])
ADD_PLUGIN([android-log], [c charon])
ADD_PLUGIN([ha], [c charon])
ADD_PLUGIN([whitelist], [c charon])
+ADD_PLUGIN([ext-auth], [c charon])
ADD_PLUGIN([lookip], [c charon])
ADD_PLUGIN([error-notify], [c charon])
ADD_PLUGIN([certexpire], [c charon])
@@ -1396,6 +1398,7 @@ AM_CONDITIONAL(USE_KERNEL_LIBIPSEC, test x$kernel_libipsec = xtrue)
AM_CONDITIONAL(USE_KERNEL_WFP, test x$kernel_wfp = xtrue)
AM_CONDITIONAL(USE_KERNEL_IPH, test x$kernel_iph = xtrue)
AM_CONDITIONAL(USE_WHITELIST, test x$whitelist = xtrue)
+AM_CONDITIONAL(USE_EXT_AUTH, test x$ext_auth = xtrue)
AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue)
AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue)
AM_CONDITIONAL(USE_CERTEXPIRE, test x$certexpire = xtrue)
@@ -1695,6 +1698,7 @@ AC_CONFIG_FILES([
src/libcharon/plugins/kernel_wfp/Makefile
src/libcharon/plugins/kernel_iph/Makefile
src/libcharon/plugins/whitelist/Makefile
+ src/libcharon/plugins/ext_auth/Makefile
src/libcharon/plugins/lookip/Makefile
src/libcharon/plugins/error_notify/Makefile
src/libcharon/plugins/certexpire/Makefile
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index e81c42405..0eaabf57f 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -258,6 +258,13 @@ if MONOLITHIC
endif
endif
+if USE_EXT_AUTH
+ SUBDIRS += plugins/ext_auth
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/ext_auth/libstrongswan-ext-auth.la
+endif
+endif
+
if USE_EAP_IDENTITY
SUBDIRS += plugins/eap_identity
if MONOLITHIC
diff --git a/src/libcharon/plugins/ext_auth/Makefile.am b/src/libcharon/plugins/ext_auth/Makefile.am
new file mode 100644
index 000000000..d51ea8881
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ext-auth.la
+else
+plugin_LTLIBRARIES = libstrongswan-ext-auth.la
+endif
+
+libstrongswan_ext_auth_la_SOURCES = ext_auth_plugin.h ext_auth_plugin.c \
+ ext_auth_listener.h ext_auth_listener.c
+
+libstrongswan_ext_auth_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_listener.c b/src/libcharon/plugins/ext_auth/ext_auth_listener.c
new file mode 100644
index 000000000..06cec20d7
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_listener.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * 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.
+ */
+
+/* for vasprintf() */
+#define _GNU_SOURCE
+#include "ext_auth_listener.h"
+
+#include <daemon.h>
+#include <utils/process.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+typedef struct private_ext_auth_listener_t private_ext_auth_listener_t;
+
+/**
+ * Private data of an ext_auth_listener_t object.
+ */
+struct private_ext_auth_listener_t {
+
+ /**
+ * Public ext_auth_listener_listener_t interface.
+ */
+ ext_auth_listener_t public;
+
+ /**
+ * Path to authorization program
+ */
+ char *script;
+};
+
+/**
+ * Allocate and push a format string to the environment
+ */
+static bool push_env(char *envp[], u_int count, char *fmt, ...)
+{
+ int i = 0;
+ char *str;
+ va_list args;
+
+ while (envp[i])
+ {
+ if (++i + 1 >= count)
+ {
+ return FALSE;
+ }
+ }
+ va_start(args, fmt);
+ if (vasprintf(&str, fmt, args) >= 0)
+ {
+ envp[i] = str;
+ }
+ va_end(args);
+ return envp[i] != NULL;
+}
+
+/**
+ * Free all allocated environment strings
+ */
+static void free_env(char *envp[])
+{
+ int i;
+
+ for (i = 0; envp[i]; i++)
+ {
+ free(envp[i]);
+ }
+}
+
+METHOD(listener_t, authorize, bool,
+ private_ext_auth_listener_t *this, ike_sa_t *ike_sa,
+ bool final, bool *success)
+{
+ if (final)
+ {
+ FILE *shell;
+ process_t *process;
+ char *envp[32] = {};
+ int out, retval;
+
+ *success = FALSE;
+
+ push_env(envp, countof(envp), "IKE_UNIQUE_ID=%u",
+ ike_sa->get_unique_id(ike_sa));
+ push_env(envp, countof(envp), "IKE_NAME=%s",
+ ike_sa->get_name(ike_sa));
+
+ push_env(envp, countof(envp), "IKE_LOCAL_HOST=%H",
+ ike_sa->get_my_host(ike_sa));
+ push_env(envp, countof(envp), "IKE_REMOTE_HOST=%H",
+ ike_sa->get_other_host(ike_sa));
+
+ push_env(envp, countof(envp), "IKE_LOCAL_ID=%Y",
+ ike_sa->get_my_id(ike_sa));
+ push_env(envp, countof(envp), "IKE_REMOTE_ID=%Y",
+ ike_sa->get_other_id(ike_sa));
+
+ if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
+ ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
+ {
+ push_env(envp, countof(envp), "IKE_REMOTE_EAP_ID=%Y",
+ ike_sa->get_other_eap_id(ike_sa));
+ }
+
+ process = process_start_shell(envp, NULL, &out, NULL,
+ "2>&1 %s", this->script);
+ if (process)
+ {
+ shell = fdopen(out, "r");
+ if (shell)
+ {
+ while (TRUE)
+ {
+ char resp[128], *e;
+
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_CFG, "error reading from ext-auth script");
+ }
+ break;
+ }
+ else
+ {
+ e = resp + strlen(resp);
+ if (e > resp && e[-1] == '\n')
+ {
+ e[-1] = '\0';
+ }
+ DBG1(DBG_CHD, "ext-auth: %s", resp);
+ }
+ }
+ fclose(shell);
+ }
+ else
+ {
+ close(out);
+ }
+ if (process->wait(process, &retval))
+ {
+ if (retval == EXIT_SUCCESS)
+ {
+ *success = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "rejecting IKE_SA for ext-auth result: %d",
+ retval);
+ }
+ }
+ }
+ free_env(envp);
+ }
+ return TRUE;
+}
+
+METHOD(ext_auth_listener_t, destroy, void,
+ private_ext_auth_listener_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ext_auth_listener_t *ext_auth_listener_create(char *script)
+{
+ private_ext_auth_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .authorize = _authorize,
+ },
+ .destroy = _destroy,
+ },
+ .script = script,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_listener.h b/src/libcharon/plugins/ext_auth/ext_auth_listener.h
new file mode 100644
index 000000000..3fec83066
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_listener.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ *
+ * 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 ext_auth_listener ext_auth_listener
+ * @{ @ingroup ext_auth
+ */
+
+#ifndef EXT_AUTH_LISTENER_H_
+#define EXT_AUTH_LISTENER_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct ext_auth_listener_t ext_auth_listener_t;
+
+/**
+ * Listener using an external script to authorize connection
+ */
+struct ext_auth_listener_t {
+
+ /**
+ * Implements listener_t interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy the listener.
+ */
+ void (*destroy)(ext_auth_listener_t *this);
+};
+
+/**
+ * Create ext_auth_listener instance.
+ *
+ * @param script path to authorization script
+ * @return listener instance
+ */
+ext_auth_listener_t *ext_auth_listener_create(char *script);
+
+#endif /** ext_auth_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_plugin.c b/src/libcharon/plugins/ext_auth/ext_auth_plugin.c
new file mode 100644
index 000000000..b3698c767
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_plugin.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * 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.
+ */
+
+#include "ext_auth_plugin.h"
+#include "ext_auth_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_ext_auth_plugin_t private_ext_auth_plugin_t;
+
+/**
+ * private data of ext_auth plugin
+ */
+struct private_ext_auth_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ ext_auth_plugin_t public;
+
+ /**
+ * Listener verifying peers during authorization
+ */
+ ext_auth_listener_t *listener;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_ext_auth_plugin_t *this)
+{
+ return "ext-auth";
+}
+
+/**
+ * Create a listener instance, NULL on error
+ */
+static ext_auth_listener_t* create_listener()
+{
+ char *script;
+
+ script = lib->settings->get_str(lib->settings,
+ "%s.plugins.ext-auth.script", NULL, lib->ns);
+ if (!script)
+ {
+ DBG1(DBG_CFG, "no script for ext-auth script defined, disabled");
+ return NULL;
+ }
+ DBG1(DBG_CFG, "using ext-auth script '%s'", script);
+ return ext_auth_listener_create(script);
+}
+
+/**
+ * Register listener
+ */
+static bool plugin_cb(private_ext_auth_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *cb_data)
+{
+ if (reg)
+ {
+ this->listener = create_listener();
+ if (!this->listener)
+ {
+ return FALSE;
+ }
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+ }
+ else
+ {
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_ext_auth_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "ext_auth"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+
+METHOD(plugin_t, reload, bool,
+ private_ext_auth_plugin_t *this)
+{
+ ext_auth_listener_t *listener;
+
+ /* reload new listener overlapped */
+ listener = create_listener();
+ if (listener)
+ {
+ charon->bus->add_listener(charon->bus, &listener->listener);
+ }
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+ this->listener = listener;
+
+ return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+ private_ext_auth_plugin_t *this)
+{
+ free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *ext_auth_plugin_create()
+{
+ private_ext_auth_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .reload = _reload,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_plugin.h b/src/libcharon/plugins/ext_auth/ext_auth_plugin.h
new file mode 100644
index 000000000..1288e240c
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_plugin.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ *
+ * 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 ext_auth ext_auth
+ * @ingroup cplugins
+ *
+ * @defgroup ext_auth_plugin ext_auth_plugin
+ * @{ @ingroup ext_auth
+ */
+
+#ifndef EXT_AUTH_PLUGIN_H_
+#define EXT_AUTH_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct ext_auth_plugin_t ext_auth_plugin_t;
+
+/**
+ * Plugin using an external script to authorize connections.
+ */
+struct ext_auth_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** EXT_AUTH_PLUGIN_H_ @}*/