ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.])
ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.])
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.])
ARG_ENABL_SET([tnc-imv], [enable TNC IMV module.])
ARG_ENABL_SET([tnccs-11], [enable TNCCS 1.1 protocol module.])
ADD_PLUGIN([eap-peap], [c libcharon])
ADD_PLUGIN([eap-tnc], [c libcharon])
ADD_PLUGIN([tnc-ifmap], [c libcharon])
+ADD_PLUGIN([tnc-pdp], [c libcharon])
ADD_PLUGIN([tnc-imc], [c libcharon])
ADD_PLUGIN([tnc-imv], [c libcharon])
ADD_PLUGIN([tnc-tnccs], [c libcharon])
AM_CONDITIONAL(USE_EAP_TNC, test x$eap_tnc = xtrue)
AM_CONDITIONAL(USE_EAP_RADIUS, test x$eap_radius = 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)
AM_CONDITIONAL(USE_TNC_IMV, test x$tnc_imv = xtrue)
AM_CONDITIONAL(USE_TNC_TNCCS, test x$tnc_tnccs = xtrue)
src/libcharon/plugins/eap_tnc/Makefile
src/libcharon/plugins/eap_radius/Makefile
src/libcharon/plugins/tnc_ifmap/Makefile
+ src/libcharon/plugins/tnc_pdp/Makefile
src/libcharon/plugins/tnc_imc/Makefile
src/libcharon/plugins/tnc_imv/Makefile
src/libcharon/plugins/tnc_tnccs/Makefile
endif
endif
+if USE_TNC_PDP
+ SUBDIRS += plugins/tnc_pdp
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/tnc_pdp/libstrongswan-tnc-pdp.la
+endif
+endif
+
if USE_TNC_IMC
SUBDIRS += plugins/tnc_imc
if MONOLITHIC
--- /dev/null
+
+INCLUDES = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
+else
+plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la
+libstrongswan_tnc_pdp_la_LIBADD = \
+ $(top_builddir)/src/libtls/libtls.la \
+ $(top_builddir)/src/libtnccs/libtnccs.la
+endif
+
+libstrongswan_tnc_pdp_la_SOURCES = \
+ tnc_pdp_plugin.h tnc_pdp_plugin.c tnc_pdp.h tnc_pdp.c
+
+libstrongswan_tnc_pdp_la_LDFLAGS = -module -avoid-version
--- /dev/null
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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 "tnc_pdp.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <daemon.h>
+#include <debug.h>
+#include <threading/thread.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_tnc_pdp_t private_tnc_pdp_t;
+
+/**
+ * Maximum size of a RADIUS IP packet
+ */
+#define MAX_PACKET 2048
+
+/**
+ * private data of tnc_pdp_t
+ */
+struct private_tnc_pdp_t {
+
+ /**
+ * implements tnc_pdp_t interface
+ */
+ tnc_pdp_t public;
+
+ /**
+ * IPv4 RADIUS socket
+ */
+ int ipv4;
+
+ /**
+ * IPv6 RADIUS socket
+ */
+ int ipv6;
+
+ /**
+ * Callback job dispatching commands
+ */
+ callback_job_t *job;
+
+};
+
+
+/**
+ * Open IPv4 or IPv6 UDP RADIUS socket
+ */
+static int open_socket(private_tnc_pdp_t *this, int family, u_int16_t port)
+{
+ int on = TRUE;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int skt;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.ss_family = family;
+
+ /* precalculate constants depending on address family */
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+
+ htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
+ htoun16(&sin->sin_port, port);
+ addrlen = sizeof(struct sockaddr_in);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+
+ memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
+ htoun16(&sin6->sin6_port, port);
+ addrlen = sizeof(struct sockaddr_in6);
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ /* open the socket */
+ skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
+ if (skt < 0)
+ {
+ DBG1(DBG_NET, "opening RADIUS socket failed: %s", strerror(errno));
+ return 0;
+ }
+ if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
+ {
+ DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ /* bind the socket */
+ if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to bind RADIUS socket: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+
+ return skt;
+}
+
+/**
+ * Process packets received on the RADIUS socket
+ */
+static job_requeue_t receive(private_tnc_pdp_t *this)
+{
+ while (TRUE)
+ {
+ char buffer[MAX_PACKET];
+ int max_fd = 0, selected = 0, bytes_read = 0;
+ fd_set rfds;
+ bool oldstate;
+ host_t *source;
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ } src;
+
+ FD_ZERO(&rfds);
+
+ if (this->ipv4)
+ {
+ FD_SET(this->ipv4, &rfds);
+ }
+ if (this->ipv6)
+ {
+ FD_SET(this->ipv6, &rfds);
+ }
+ max_fd = max(this->ipv4, this->ipv6);
+
+ DBG2(DBG_NET, "waiting for data on RADIUS sockets");
+ oldstate = thread_cancelability(TRUE);
+ if (select(max_fd + 1, &rfds, NULL, NULL, NULL) <= 0)
+ {
+ thread_cancelability(oldstate);
+ continue;
+ }
+ thread_cancelability(oldstate);
+
+ if (FD_ISSET(this->ipv4, &rfds))
+ {
+ selected = this->ipv4;
+ }
+ else if (FD_ISSET(this->ipv6, &rfds))
+ {
+ selected = this->ipv6;
+ }
+ else
+ {
+ /* oops, shouldn't happen */
+ continue;
+ }
+
+ /* read received packet */
+ msg.msg_name = &src;
+ msg.msg_namelen = sizeof(src);
+ iov.iov_base = buffer;
+ iov.iov_len = MAX_PACKET;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+
+ bytes_read = recvmsg(selected, &msg, 0);
+ if (bytes_read < 0)
+ {
+ DBG1(DBG_NET, "error reading RADIUS socket: %s", strerror(errno));
+ continue;
+ }
+ if (msg.msg_flags & MSG_TRUNC)
+ {
+ DBG1(DBG_NET, "receive buffer too small, RADIUS packet discarded");
+ continue;
+ }
+ source = host_create_from_sockaddr((sockaddr_t*)&src);
+ DBG2(DBG_NET, "received RADIUS packet from %#H", source);
+ DBG3(DBG_NET, "%b", buffer, bytes_read);
+ source->destroy(source);
+ }
+ return JOB_REQUEUE_FAIR;
+}
+
+METHOD(tnc_pdp_t, destroy, void,
+ private_tnc_pdp_t *this)
+{
+ this->job->cancel(this->job);
+ if (this->ipv4)
+ {
+ close(this->ipv4);
+ }
+ if (this->ipv6)
+ {
+ close(this->ipv6);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+tnc_pdp_t *tnc_pdp_create(u_int16_t port)
+{
+ private_tnc_pdp_t *this;
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .ipv4 = open_socket(this, AF_INET, port),
+ .ipv6 = open_socket(this, AF_INET6, port),
+ );
+
+ if (!this->ipv4 && !this->ipv6)
+ {
+ DBG1(DBG_NET, "couldd not create any RADIUS sockets");
+ destroy(this);
+ return NULL;
+ }
+ if (!this->ipv4)
+ {
+ DBG1(DBG_NET, "could not open IPv4 RADIUS socket, IPv4 disabled");
+ }
+ if (!this->ipv6)
+ {
+ DBG1(DBG_NET, "could not open IPv6 RADIUS socket, IPv6 disabled");
+ }
+
+ this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
+ this, NULL, NULL, JOB_PRIO_CRITICAL);
+ lib->processor->queue_job(lib->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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 tnc_pdp tnc_pdp
+ * @{ @ingroup tnc_pdp
+ */
+
+#ifndef TNC_PDP_H_
+#define TNC_PDP_H_
+
+typedef struct tnc_pdp_t tnc_pdp_t;
+
+#include <library.h>
+
+/**
+ * Public interface of a TNC Policy Decision Point object
+ */
+struct tnc_pdp_t {
+
+ /**
+ * implements plugin interface
+ */
+ void (*destroy)(tnc_pdp_t *this);
+};
+
+/**
+ * Create a TNC PDP instance
+ *
+ * @param port RADIUS port of TNC PDP
+ */
+tnc_pdp_t* tnc_pdp_create(u_int16_t port);
+
+#endif /** TNC_PDP_PLUGIN_H_ @}*/
--- /dev/null
+/*
+ * Copyright (C) 2010 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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 "tnc_pdp_plugin.h"
+#include "tnc_pdp.h"
+
+typedef struct private_tnc_pdp_plugin_t private_tnc_pdp_plugin_t;
+
+/**
+ * Default RADIUS port, when not configured
+ */
+#define RADIUS_PORT 1812
+
+/**
+ * private data of tnc_pdp plugin
+ */
+struct private_tnc_pdp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ tnc_pdp_plugin_t public;
+
+ /**
+ * Policy Decision Point object
+ */
+ tnc_pdp_t *pdp;
+
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_tnc_pdp_plugin_t *this)
+{
+ return "tnc-pdp";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_tnc_pdp_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_PROVIDE(CUSTOM, "tnc-pdp"),
+ PLUGIN_DEPENDS(CUSTOM, "imv-manager"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_tnc_pdp_plugin_t *this)
+{
+ DESTROY_IF(this->pdp);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *tnc_pdp_plugin_create()
+{
+ private_tnc_pdp_plugin_t *this;
+ int port;
+
+ port = lib->settings->get_int(lib->settings,
+ "charon.plugins.tnc_pdp.radius_port", RADIUS_PORT);
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ .pdp = tnc_pdp_create(port),
+ );
+
+ return &this->public.plugin;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2011 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * 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 tnc_pdp tnc_pdp
+ * @ingroup cplugins
+ *
+ * @defgroup tnc_pdp_plugin tnc_pdp_plugin
+ * @{ @ingroup tnc_pdp
+ */
+
+#ifndef TNC_PDP_PLUGIN_H_
+#define TNC_PDP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct tnc_pdp_plugin_t tnc_pdp_plugin_t;
+
+/**
+ * TNC-PDP plugin
+ */
+struct tnc_pdp_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** TNC_PDP_PLUGIN_H_ @}*/
echo -n " --enable-eap-tnc" >> $INSTALLSHELL
fi
+if [ "$USE_TNC_PDP" = "yes" ]
+then
+ echo -n " --enable-tnc-pdp" >> $INSTALLSHELL
+fi
+
if [ "$USE_TNC_IMC" = "yes" ]
then
echo -n " --enable-tnc-imc" >> $INSTALLSHELL
USE_EAP_TTLS="yes"
USE_EAP_PEAP="yes"
USE_EAP_TNC="yes"
+USE_TNC_PDP="yes"
USE_TNC_IMC="yes"
USE_TNC_IMV="yes"
USE_TNCCS_11="yes"