From 81c63b0eed39432878f78727f60a1e7499645199 Mon Sep 17 00:00:00 2001 From: Yves-Alexis Perez Date: Fri, 11 Jul 2014 07:23:31 +0200 Subject: Imported Upstream version 5.2.0 --- src/libcharon/plugins/tnc_pdp/Makefile.am | 2 +- src/libcharon/plugins/tnc_pdp/Makefile.in | 8 ++- src/libcharon/plugins/tnc_pdp/tnc_pdp.c | 91 ++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 5 deletions(-) (limited to 'src/libcharon/plugins/tnc_pdp') 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 #include +#include #include #include @@ -37,7 +38,7 @@ #include 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 */ @@ -98,6 +101,11 @@ struct private_tnc_pdp_t { */ chunk_t secret; + /** + * RADIUS clients + */ + linked_list_t *clients; + /** * MD5 hasher */ @@ -120,6 +128,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 */ @@ -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); -- cgit v1.2.3