summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/tnc_pdp
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
committerYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
commit81c63b0eed39432878f78727f60a1e7499645199 (patch)
tree82387d8fecd1c20788fd8bd784a9b0bde091fb6b /src/libcharon/plugins/tnc_pdp
parentc5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9 (diff)
downloadvyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.tar.gz
vyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.zip
Imported Upstream version 5.2.0
Diffstat (limited to 'src/libcharon/plugins/tnc_pdp')
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.am2
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in8
-rw-r--r--src/libcharon/plugins/tnc_pdp/tnc_pdp.c91
3 files changed, 96 insertions, 5 deletions
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am
index 48de82571..3478c5b30 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.am
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.am
@@ -9,7 +9,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpttls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 875aa99d1..531c00c0c 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -270,6 +270,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -288,6 +289,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -315,6 +317,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -406,6 +409,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpttls
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
index 89237f564..109c216d5 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <unistd.h>
+#include <time.h>
#include <radius_message.h>
#include <radius_mppe.h>
@@ -37,7 +38,7 @@
#include <sa/eap/eap_method.h>
typedef struct private_tnc_pdp_t private_tnc_pdp_t;
-
+typedef struct client_entry_t client_entry_t;
/**
* Default RADIUS port, when not configured
*/
@@ -48,6 +49,8 @@ typedef struct private_tnc_pdp_t private_tnc_pdp_t;
*/
#define MAX_PACKET 4096
+#define RADIUS_RETRANSMIT_TIMEOUT 30 /* seconds */
+
/**
* private data of tnc_pdp_t
*/
@@ -99,6 +102,11 @@ struct private_tnc_pdp_t {
chunk_t secret;
/**
+ * RADIUS clients
+ */
+ linked_list_t *clients;
+
+ /**
* MD5 hasher
*/
hasher_t *hasher;
@@ -121,6 +129,33 @@ struct private_tnc_pdp_t {
};
/**
+ * Client entry helping to detect RADIUS packet retransmissions
+ */
+struct client_entry_t {
+
+ /**
+ * IP host address and port of client
+ */
+ host_t *host;
+
+ /**
+ * Time of last RADIUS Access-Request received from client
+ */
+ time_t last_time;
+
+ /**
+ * Identifier of last RADIUS Access-Request received from client
+ */
+ uint8_t last_id;
+};
+
+static void free_client_entry(client_entry_t *this)
+{
+ this->host->destroy(this->host);
+ free(this);
+}
+
+/**
* Open IPv4 or IPv6 UDP socket
*/
static int open_udp_socket(int family, u_int16_t port)
@@ -663,16 +698,24 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
{
radius_message_t *request;
char buffer[MAX_PACKET];
+ client_entry_t *client;
+ bool retransmission = FALSE, found = FALSE, stale;
+ enumerator_t *enumerator;
int bytes_read = 0;
host_t *source;
+ uint8_t id;
+ time_t now;
+
union {
struct sockaddr_in in4;
struct sockaddr_in6 in6;
} src;
+
struct iovec iov = {
.iov_base = buffer,
.iov_len = MAX_PACKET,
};
+
struct msghdr msg = {
.msg_name = &src,
.msg_namelen = sizeof(src),
@@ -704,7 +747,46 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
if (request->verify(request, NULL, this->secret, this->hasher,
this->signer))
{
- process_eap(this, request, source);
+ id = request->get_identifier(request);
+ now = time(NULL);
+
+ enumerator = this->clients->create_enumerator(this->clients);
+ while (enumerator->enumerate(enumerator, &client))
+ {
+ stale = client->last_time < now - RADIUS_RETRANSMIT_TIMEOUT;
+
+ if (source->equals(source, client->host))
+ {
+ retransmission = !stale && client->last_id == id;
+ client->last_id = id;
+ client->last_time = now;
+ found = TRUE;
+ }
+ else if (stale)
+ {
+ this->clients->remove_at(this->clients, enumerator);
+ free_client_entry(client);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!found)
+ {
+ client = malloc_thing(client_entry_t);
+ client->host = source->clone(source);
+ client->last_id = id;
+ client->last_time = now;
+ this->clients->insert_last(this->clients, client);
+ }
+ if (retransmission)
+ {
+ DBG1(DBG_CFG, "ignoring RADIUS Access-Request 0x%02x, "
+ "already processing", id);
+ }
+ else
+ {
+ process_eap(this, request, source);
+ }
}
request->destroy(request);
}
@@ -739,6 +821,10 @@ METHOD(tnc_pdp_t, destroy, void,
lib->watcher->remove(lib->watcher, this->radius_ipv6);
close(this->radius_ipv6);
}
+ if (this->clients)
+ {
+ this->clients->destroy_function(this->clients, (void*)free_client_entry);
+ }
DESTROY_IF(this->server);
DESTROY_IF(this->signer);
DESTROY_IF(this->hasher);
@@ -843,6 +929,7 @@ tnc_pdp_t *tnc_pdp_create(void)
this->radius_ipv4 = open_udp_socket(AF_INET, radius_port);
this->radius_ipv6 = open_udp_socket(AF_INET6, radius_port);
this->secret = chunk_from_str(secret);
+ this->clients = linked_list_create();
this->type = eap_type_from_string(eap_type_str);
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);