]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
narrowid: Add a plugin narrowing remote TS to authenticated IKE IPv4/IPv6 IDs
authorMartin Willi <martin@revosec.ch>
Fri, 30 Jan 2015 14:37:48 +0000 (15:37 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 24 Feb 2015 16:13:58 +0000 (17:13 +0100)
conf/Makefile.am
conf/plugins/narrowid.opt [new file with mode: 0644]
configure.ac
src/libcharon/Makefile.am
src/libcharon/plugins/narrowid/Makefile.am [new file with mode: 0644]
src/libcharon/plugins/narrowid/narrowid_narrow.c [new file with mode: 0644]
src/libcharon/plugins/narrowid/narrowid_narrow.h [new file with mode: 0644]
src/libcharon/plugins/narrowid/narrowid_plugin.c [new file with mode: 0644]
src/libcharon/plugins/narrowid/narrowid_plugin.h [new file with mode: 0644]

index 1d0cfde777dd890a176ad373ec70af39af089011..221b2a48cc81dca8bfb5b542a2966eae446ec95d 100644 (file)
@@ -67,6 +67,7 @@ plugins = \
        plugins/kernel-pfroute.opt \
        plugins/load-tester.opt \
        plugins/lookip.opt \
+       plugins/narrowid.opt \
        plugins/ntru.opt \
        plugins/openssl.opt \
        plugins/pkcs11.opt \
diff --git a/conf/plugins/narrowid.opt b/conf/plugins/narrowid.opt
new file mode 100644 (file)
index 0000000..967ac3e
--- /dev/null
@@ -0,0 +1,7 @@
+charon.plugins.narrowid.configs =
+       Space separated list of CHILD_SA configurations to do narrowing for.
+
+       For matching CHILD_SA configuration names, the plugin narrows the remote
+       traffic selectors to any succesfully authenticated IPv4 or IPv6 IKE
+       identity. Multiple configurations can be separated by spaces, no narrowing
+       is done if the option is not set.
index 2d77652d1194c7387ec157111026f0ca3c8405b2..cd732df6e1b7d9ca656e3c0a8b50947b1606d35c 100644 (file)
@@ -194,6 +194,7 @@ 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([narrowid],       [enables plugin narrowing remote traffic selectors to authenticated IDs.])
 ARG_ENABL_SET([keychain],       [enables OS X Keychain Services credential set.])
 ARG_ENABL_SET([pkcs11],         [enables the PKCS11 token support plugin.])
 ARG_DISBL_SET([revocation],     [disable X509 CRL/OCSP revocation check plugin.])
@@ -1336,6 +1337,7 @@ ADD_PLUGIN([radattr],              [c charon])
 ADD_PLUGIN([maemo],                [c charon])
 ADD_PLUGIN([uci],                  [c charon])
 ADD_PLUGIN([addrblock],            [c charon])
+ADD_PLUGIN([narrowid],             [c charon])
 ADD_PLUGIN([unity],                [c charon])
 
 AC_SUBST(charon_plugins)
@@ -1492,6 +1494,7 @@ AM_CONDITIONAL(USE_CONNMARK, test x$connmark = xtrue)
 AM_CONDITIONAL(USE_FORECAST, test x$forecast = xtrue)
 AM_CONDITIONAL(USE_FARP, test x$farp = xtrue)
 AM_CONDITIONAL(USE_ADDRBLOCK, test x$addrblock = xtrue)
+AM_CONDITIONAL(USE_NARROWID, test x$narrowid = xtrue)
 AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue)
 AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue)
 AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue)
@@ -1735,6 +1738,7 @@ AC_CONFIG_FILES([
        src/libcharon/plugins/medsrv/Makefile
        src/libcharon/plugins/medcli/Makefile
        src/libcharon/plugins/addrblock/Makefile
+       src/libcharon/plugins/narrowid/Makefile
        src/libcharon/plugins/unity/Makefile
        src/libcharon/plugins/uci/Makefile
        src/libcharon/plugins/ha/Makefile
index 7d6e86bd548ae8da64552ad52878dd2ab6489a50..89075788dc0b711e9b29125a58a34a05ffc1d165 100644 (file)
@@ -608,6 +608,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_NARROWID
+  SUBDIRS += plugins/narrowid
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/narrowid/libstrongswan-narrowid.la
+endif
+endif
+
 if USE_UNITY
   SUBDIRS += plugins/unity
 if MONOLITHIC
diff --git a/src/libcharon/plugins/narrowid/Makefile.am b/src/libcharon/plugins/narrowid/Makefile.am
new file mode 100644 (file)
index 0000000..b8d4789
--- /dev/null
@@ -0,0 +1,19 @@
+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-narrowid.la
+else
+plugin_LTLIBRARIES = libstrongswan-narrowid.la
+endif
+
+libstrongswan_narrowid_la_SOURCES = \
+       narrowid_narrow.h narrowid_narrow.c \
+       narrowid_plugin.h narrowid_plugin.c
+
+libstrongswan_narrowid_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/narrowid/narrowid_narrow.c b/src/libcharon/plugins/narrowid/narrowid_narrow.c
new file mode 100644 (file)
index 0000000..3efb66a
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 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 "narrowid_narrow.h"
+
+#include <daemon.h>
+
+typedef struct private_narrowid_narrow_t private_narrowid_narrow_t;
+
+/**
+ * Private data of an narrowid_narrow_t object.
+ */
+struct private_narrowid_narrow_t {
+
+       /**
+        * Public narrowid_narrow_t interface.
+        */
+       narrowid_narrow_t public;
+
+       /**
+        * Space separated list of configs we do narrowing for
+        */
+       char *configs;
+};
+
+/**
+ * Narrow list of traffic selectors to authenticated remote identities
+ */
+static void narrow_to_ids(private_narrowid_narrow_t *this,
+                                                 ike_sa_t *ike_sa, linked_list_t *list)
+{
+       traffic_selector_t *current, *ts, *subset;
+       enumerator_t *enumerator;
+       identification_t *id;
+       linked_list_t *orig;
+       auth_cfg_t *auth;
+       ts_type_t type;
+
+       orig = linked_list_create();
+
+       while (list->remove_first(list, (void**)&current) == SUCCESS)
+       {
+               orig->insert_last(orig, current);
+       }
+
+       while (orig->remove_first(orig, (void**)&current) == SUCCESS)
+       {
+               enumerator = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+               while (enumerator->enumerate(enumerator, &auth))
+               {
+                       id = auth->get(auth, AUTH_RULE_IDENTITY);
+                       if (id)
+                       {
+                               switch (id->get_type(id))
+                               {
+                                       case ID_IPV4_ADDR:
+                                               type = TS_IPV4_ADDR_RANGE;
+                                               break;
+                                       case ID_IPV6_ADDR:
+                                               type = TS_IPV6_ADDR_RANGE;
+                                               break;
+                                       default:
+                                               continue;
+                               }
+                               ts = traffic_selector_create_from_bytes(0, type,
+                                               id->get_encoding(id), 0, id->get_encoding(id), 65535);
+                               if (ts)
+                               {
+                                       subset = current->get_subset(current, ts);
+                                       if (subset)
+                                       {
+                                               list->insert_last(list, subset);
+                                       }
+                                       ts->destroy(ts);
+                               }
+                       }
+               }
+               enumerator->destroy(enumerator);
+
+               current->destroy(current);
+       }
+
+       orig->destroy(orig);
+
+       if (list->get_count(list))
+       {
+               DBG1(DBG_CFG, "narrowed selectors to peer identities: %#R", list);
+       }
+       else
+       {
+               DBG1(DBG_CFG, "narrowing selectors to peer identites gives empty set");
+       }
+}
+
+/**
+ * Check if we should do narrowing for the given CHILD_SA config
+ */
+static bool do_narrowing_for(private_narrowid_narrow_t *this, char *config)
+{
+       enumerator_t *enumerator;
+       char *token;
+       bool found = FALSE;
+
+       if (!this->configs)
+       {       /* none by default */
+               return FALSE;
+       }
+
+       enumerator = enumerator_create_token(this->configs, " ", "");
+       while (enumerator->enumerate(enumerator, &token))
+       {
+               if (streq(token, config))
+               {
+                       found = TRUE;
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return found;
+}
+
+METHOD(listener_t, narrow, bool,
+       private_narrowid_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+       narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
+{
+       switch (type)
+       {
+               case NARROW_RESPONDER:
+               case NARROW_INITIATOR_POST_AUTH:
+               case NARROW_INITIATOR_POST_NOAUTH:
+                       if (do_narrowing_for(this, child_sa->get_name(child_sa)))
+                       {
+                               narrow_to_ids(this, ike_sa, remote);
+                       }
+                       break;
+               default:
+                       break;
+       }
+       return TRUE;
+}
+
+METHOD(narrowid_narrow_t, destroy, void,
+       private_narrowid_narrow_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+narrowid_narrow_t *narrowid_narrow_create()
+{
+       private_narrowid_narrow_t *this;
+
+       INIT(this,
+               .public = {
+                       .listener = {
+                               .narrow = _narrow,
+                       },
+                       .destroy = _destroy,
+               },
+               .configs = lib->settings->get_str(lib->settings,
+                                                               "%s.plugins.narrowid.configs", NULL, lib->ns),
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/narrowid/narrowid_narrow.h b/src/libcharon/plugins/narrowid/narrowid_narrow.h
new file mode 100644 (file)
index 0000000..9ac1195
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 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 narrowid_narrow narrowid_narrow
+ * @{ @ingroup narrowid
+ */
+
+#ifndef NARROWID_NARROW_H_
+#define NARROWID_NARROW_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct narrowid_narrow_t narrowid_narrow_t;
+
+/**
+ * Listener narrowing remote traffic selectors to authenticated IKE IDs.
+ */
+struct narrowid_narrow_t {
+
+       /**
+        * Implements listener_t.
+        */
+       listener_t listener;
+
+       /**
+        * Destroy a narrowid_narrow_t.
+        */
+       void (*destroy)(narrowid_narrow_t *this);
+};
+
+/**
+ * Create a narrowid_narrow instance.
+ */
+narrowid_narrow_t *narrowid_narrow_create();
+
+#endif /** NARROWID_NARROW_H_ @}*/
diff --git a/src/libcharon/plugins/narrowid/narrowid_plugin.c b/src/libcharon/plugins/narrowid/narrowid_plugin.c
new file mode 100644 (file)
index 0000000..14d1207
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 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 "narrowid_plugin.h"
+#include "narrowid_narrow.h"
+
+#include <daemon.h>
+
+typedef struct private_narrowid_plugin_t private_narrowid_plugin_t;
+
+/**
+ * private data of narrowid_plugin
+ */
+struct private_narrowid_plugin_t {
+
+       /**
+        * public functions
+        */
+       narrowid_plugin_t public;
+
+       /**
+        * Listener to narrow TS list
+        */
+       narrowid_narrow_t *narrower;
+};
+
+METHOD(plugin_t, get_name, char*,
+       private_narrowid_plugin_t *this)
+{
+       return "narrowid";
+}
+
+/**
+ * Register listener
+ */
+static bool plugin_cb(private_narrowid_plugin_t *this,
+                                         plugin_feature_t *feature, bool reg, void *cb_data)
+{
+       if (reg)
+       {
+               charon->bus->add_listener(charon->bus, &this->narrower->listener);
+       }
+       else
+       {
+               charon->bus->remove_listener(charon->bus, &this->narrower->listener);
+       }
+       return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+       private_narrowid_plugin_t *this, plugin_feature_t *features[])
+{
+       static plugin_feature_t f[] = {
+               PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+                       PLUGIN_PROVIDE(CUSTOM, "narrowid"),
+       };
+       *features = f;
+       return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+       private_narrowid_plugin_t *this)
+{
+       this->narrower->destroy(this->narrower);
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *narrowid_plugin_create()
+{
+       private_narrowid_plugin_t *this;
+
+       INIT(this,
+               .public = {
+                       .plugin = {
+                               .get_name = _get_name,
+                               .get_features = _get_features,
+                               .destroy = _destroy,
+                       },
+               },
+               .narrower = narrowid_narrow_create(),
+       );
+
+       return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/narrowid/narrowid_plugin.h b/src/libcharon/plugins/narrowid/narrowid_plugin.h
new file mode 100644 (file)
index 0000000..380d8e4
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 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 narrowid narrowid
+ * @ingroup cplugins
+ *
+ * @defgroup narrowid_plugin narrowid_plugin
+ * @{ @ingroup narrowid
+ */
+
+#ifndef NARROWID_PLUGIN_H_
+#define NARROWID_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct narrowid_plugin_t narrowid_plugin_t;
+
+/**
+ * Plugin narrowing remote traffic selectors to its authenticated IKE IDs.
+ */
+struct narrowid_plugin_t {
+
+       /**
+        * Implements plugin_t. interface.
+        */
+       plugin_t plugin;
+};
+
+#endif /** NARROWID_PLUGIN_H_ @}*/