diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2012-06-28 21:16:07 +0200 |
commit | b34738ed08c2227300d554b139e2495ca5da97d6 (patch) | |
tree | 62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libcharon/plugins | |
parent | 0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff) | |
download | vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip |
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libcharon/plugins')
273 files changed, 14493 insertions, 4277 deletions
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index 57aab1db7..3139e20b0 100644 --- a/src/libcharon/plugins/addrblock/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in index 08248da12..50e5f638e 100644 --- a/src/libcharon/plugins/android/Makefile.in +++ b/src/libcharon/plugins/android/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c index ec3ff7a51..a53962f16 100644 --- a/src/libcharon/plugins/android/android_handler.c +++ b/src/libcharon/plugins/android/android_handler.c @@ -1,6 +1,6 @@ /* + * Copyright (C) 2010-2011 Tobias Brunner * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -36,9 +36,20 @@ struct private_android_handler_t { * List of registered DNS servers */ linked_list_t *dns; + + /** + * Whether the VPN frontend is used + */ + bool frontend; }; /** + * Prefixes to be used when installing DNS servers + */ +#define DNS_PREFIX_DEFAULT "net" +#define DNS_PREFIX_FRONTEND "vpn" + +/** * Struct to store a pair of old and installed DNS servers */ typedef struct { @@ -70,12 +81,13 @@ bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out) /** * Read DNS server property with a given index */ -host_t *get_dns_server(int index) +host_t *get_dns_server(private_android_handler_t *this, int index) { host_t *dns = NULL; - char key[10], value[PROPERTY_VALUE_MAX]; + char key[10], value[PROPERTY_VALUE_MAX], + *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; - if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key)) + if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) { return NULL; } @@ -90,11 +102,12 @@ host_t *get_dns_server(int index) /** * Set DNS server property with a given index */ -bool set_dns_server(int index, host_t *dns) +bool set_dns_server(private_android_handler_t *this, int index, host_t *dns) { - char key[10], value[PROPERTY_VALUE_MAX]; + char key[10], value[PROPERTY_VALUE_MAX], + *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; - if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key)) + if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) { return FALSE; } @@ -136,8 +149,8 @@ METHOD(attribute_handler_t, handle, bool, pair = malloc_thing(dns_pair_t); pair->dns = dns; index = this->dns->get_count(this->dns) + 1; - pair->old = get_dns_server(index); - set_dns_server(index, dns); + pair->old = get_dns_server(this, index); + set_dns_server(this, index, dns); this->dns->insert_last(this->dns, pair); return TRUE; } @@ -164,7 +177,7 @@ METHOD(attribute_handler_t, release, void, if (chunk_equals(pair->dns->get_address(pair->dns), data)) { this->dns->remove_at(this->dns, enumerator); - set_dns_server(index, pair->old); + set_dns_server(this, index, pair->old); destroy_dns_pair(pair); } } @@ -204,7 +217,7 @@ METHOD(android_handler_t, destroy, void, /** * See header */ -android_handler_t *android_handler_create() +android_handler_t *android_handler_create(bool frontend) { private_android_handler_t *this; @@ -218,6 +231,7 @@ android_handler_t *android_handler_create() .destroy = _destroy, }, .dns = linked_list_create(), + .frontend = frontend, ); return &this->public; diff --git a/src/libcharon/plugins/android/android_handler.h b/src/libcharon/plugins/android/android_handler.h index af620505b..0170958ee 100644 --- a/src/libcharon/plugins/android/android_handler.h +++ b/src/libcharon/plugins/android/android_handler.h @@ -1,6 +1,6 @@ /* + * Copyright (C) 2010-2011 Tobias Brunner * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -44,7 +44,9 @@ struct android_handler_t { /** * Create a android_handler instance. + * + * @param frontend TRUE if the VPN frontend is used */ -android_handler_t *android_handler_create(); +android_handler_t *android_handler_create(bool frontend); #endif /** ANDROID_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android/android_logger.c index 43c56e656..f7624b2c7 100644 --- a/src/libcharon/plugins/android/android_logger.c +++ b/src/libcharon/plugins/android/android_logger.c @@ -47,18 +47,19 @@ METHOD(listener_t, log_, bool, { if (level <= this->level) { + int prio = level > 1 ? ANDROID_LOG_DEBUG : ANDROID_LOG_INFO; char sgroup[16], buffer[8192]; char *current = buffer, *next; snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group); vsnprintf(buffer, sizeof(buffer), format, args); while (current) - { /* log each line seperately */ + { /* log each line separately */ next = strchr(current, '\n'); if (next) { *(next++) = '\0'; } - __android_log_print(ANDROID_LOG_INFO, "charon", "%.2d[%s] %s\n", + __android_log_print(prio, "charon", "%.2d[%s] %s\n", thread, sgroup, current); current = next; } diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c index 54a7017a1..091f34a8e 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android/android_plugin.c @@ -92,21 +92,16 @@ plugin_t *android_plugin_create() }, }, .logger = android_logger_create(), - .handler = android_handler_create(), .creds = android_creds_create(), ); + this->service = android_service_create(this->creds); + this->handler = android_handler_create(this->service != NULL); + charon->bus->add_listener(charon->bus, &this->logger->listener); lib->credmgr->add_set(lib->credmgr, &this->creds->set); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); - this->service = android_service_create(this->creds); - if (!this->service) - { - destroy(this); - return NULL; - } - return &this->public.plugin; } diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am new file mode 100644 index 000000000..9aa0daad3 --- /dev/null +++ b/src/libcharon/plugins/certexpire/Makefile.am @@ -0,0 +1,19 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-certexpire.la +else +plugin_LTLIBRARIES = libstrongswan-certexpire.la +endif + +libstrongswan_certexpire_la_SOURCES = certexpire_plugin.h certexpire_plugin.c \ + certexpire_listener.h certexpire_listener.c \ + certexpire_export.h certexpire_export.c \ + certexpire_cron.h certexpire_cron.c + +libstrongswan_certexpire_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in new file mode 100644 index 000000000..929cce20c --- /dev/null +++ b/src/libcharon/plugins/certexpire/Makefile.in @@ -0,0 +1,621 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/certexpire +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_certexpire_la_LIBADD = +am_libstrongswan_certexpire_la_OBJECTS = certexpire_plugin.lo \ + certexpire_listener.lo certexpire_export.lo certexpire_cron.lo +libstrongswan_certexpire_la_OBJECTS = \ + $(am_libstrongswan_certexpire_la_OBJECTS) +libstrongswan_certexpire_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_certexpire_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_certexpire_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_certexpire_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_certexpire_la_SOURCES) +DIST_SOURCES = $(libstrongswan_certexpire_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-certexpire.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-certexpire.la +libstrongswan_certexpire_la_SOURCES = certexpire_plugin.h certexpire_plugin.c \ + certexpire_listener.h certexpire_listener.c \ + certexpire_export.h certexpire_export.c \ + certexpire_cron.h certexpire_cron.c + +libstrongswan_certexpire_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/certexpire/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/certexpire/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-certexpire.la: $(libstrongswan_certexpire_la_OBJECTS) $(libstrongswan_certexpire_la_DEPENDENCIES) + $(libstrongswan_certexpire_la_LINK) $(am_libstrongswan_certexpire_la_rpath) $(libstrongswan_certexpire_la_OBJECTS) $(libstrongswan_certexpire_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certexpire_cron.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certexpire_export.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certexpire_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certexpire_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/certexpire/certexpire_cron.c b/src/libcharon/plugins/certexpire/certexpire_cron.c new file mode 100644 index 000000000..e8cd4bfd8 --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_cron.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 "certexpire_cron.h" + +#include <time.h> + +#include <debug.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_certexpire_cron_t private_certexpire_cron_t; + +/** + * Private data of an certexpire_cron_t object. + */ +struct private_certexpire_cron_t { + + /** + * Public certexpire_cron_t interface. + */ + certexpire_cron_t public; + + /** + * time when to run export job + */ + struct { + bool m[60]; + bool h[24]; + bool d[32]; + bool my[13]; + bool dw[8]; + } cron; + + /** + * Callback function to execute + */ + certexpire_cron_job_t job; + + /** + * Data to pass to callback + */ + void *data; +}; + +/** + * Check if we should execute the export job + */ +static job_requeue_t check_cron(private_certexpire_cron_t *this) +{ + struct tm tm; + time_t t; + + t = time(NULL); + localtime_r(&t, &tm); + + /* recheck every minute at second 0 */ + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)check_cron, + this, NULL, NULL, JOB_PRIO_CRITICAL), 60 - tm.tm_sec); + + /* skip this minute if we had a large negative time shift */ + if (tm.tm_sec <= 30) + { + if (this->cron.m[tm.tm_min] && + this->cron.h[tm.tm_hour] && + this->cron.d[tm.tm_mday] && + this->cron.my[tm.tm_mon + 1] && + (this->cron.dw[tm.tm_wday] || + (this->cron.dw[7] && tm.tm_wday == 0))) + { + this->job(this->data); + } + } + return JOB_REQUEUE_NONE; +} + +/** + * Parse a cron range component into boolean fields + */ +static void parse_ranges(bool *fields, char *label, int mi, int ma, char *range) +{ + enumerator_t *enumerator; + int from, to, i; + + if (streq(range, "*")) + { + for (i = mi; i <= ma; i++) + { + fields[i] = TRUE; + } + } + else + { + enumerator = enumerator_create_token(range, ",", ""); + while (enumerator->enumerate(enumerator, &range)) + { + switch (sscanf(range, "%d-%d", &from, &to)) + { + case 1: /* single value */ + if (from >= mi && from <= ma) + { + fields[from] = TRUE; + } + else + { + DBG1(DBG_CFG, "ignoring cron %s %d, out of range", + label, from); + } + break; + case 2: /* range */ + if (from < mi) + { + DBG1(DBG_CFG, "cron %s out of range, shortening start " + "from %d to %d", label, from, mi); + from = mi; + } + if (to > ma) + { + DBG1(DBG_CFG, "cron %s out of range, shortening end " + "from %d to %d", label, to, ma); + to = ma; + } + for (i = from; i <= to; i++) + { + fields[i] = TRUE; + } + break; + default: + break; + } + } + enumerator->destroy(enumerator); + } + DBG3(DBG_CFG, "cron job with enabled %ss:", label); + for (i = mi; i <= ma; i++) + { + if (fields[i]) + { + DBG3(DBG_CFG, " %d", i); + } + } +} + +/** + * Start cron processing, if configured + */ +static void start_cron(private_certexpire_cron_t *this, char *cron) +{ + enumerator_t *enumerator; + int i = 0; + + enumerator = enumerator_create_token(cron, " ", " "); + for (i = 0; i < 5; i++) + { + if (!enumerator->enumerate(enumerator, &cron)) + { + DBG1(DBG_CFG, "cron misses a field, using '*'"); + cron = "*"; + } + switch (i) + { + case 0: + parse_ranges(this->cron.m, "minute", 0, 59, cron); + break; + case 1: + parse_ranges(this->cron.h, "hour", 0, 23, cron); + break; + case 2: + parse_ranges(this->cron.d, "day", 1, 31, cron); + break; + case 3: + parse_ranges(this->cron.my, "month", 1, 12, cron); + break; + case 4: + parse_ranges(this->cron.dw, "weekday", 0, 7, cron); + break; + default: + break; + } + } + if (enumerator->enumerate(enumerator, &cron)) + { + DBG1(DBG_CFG, "ignoring extra fields in cron"); + } + enumerator->destroy(enumerator); + + check_cron(this); +} + +METHOD(certexpire_cron_t, destroy, void, + private_certexpire_cron_t *this) +{ + free(this); +} + +/** + * See header + */ +certexpire_cron_t *certexpire_cron_create(char *cron, certexpire_cron_job_t job, + void *data) +{ + private_certexpire_cron_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .job = job, + .data = data, + ); + + start_cron(this, cron); + + return &this->public; +} diff --git a/src/libcharon/plugins/certexpire/certexpire_cron.h b/src/libcharon/plugins/certexpire/certexpire_cron.h new file mode 100644 index 000000000..0d6623d7f --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_cron.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 certexpire_cron certexpire_cron + * @{ @ingroup certexpire + */ + +#ifndef CERTEXPIRE_CRON_H_ +#define CERTEXPIRE_CRON_H_ + +typedef struct certexpire_cron_t certexpire_cron_t; + +/** + * Callback function invoked by cron. + * + * @param data user specified callback data + */ +typedef void (*certexpire_cron_job_t)(void *data); + +/** + * Cron style job scheduling. + */ +struct certexpire_cron_t { + + /** + * Destroy a certexpire_cron_t. + * + * It currently is not possible to savely cancel a cron job. Make sure + * any scheduled jobs have been canceled before cleaning up. + */ + void (*destroy)(certexpire_cron_t *this); +}; + +/** + * Create a certexpire_cron instance. + * + * The cron string takes numeric arguments only, but supports ranges (1-5) + * and selections (1,3,5), or a combination, space separated: + * minute hour day month weekday + * minute, 0-59 + * hour, 0-23 + * day, 1-31 + * month, 1-12 + * weekday, 0-7 (0 == 7 == sunday) + * man crontab(5) for details. + * + * @param cron cron style scheduling string + * @param job callback function to invoke + * @param data user data to pass to job + */ +certexpire_cron_t *certexpire_cron_create(char *cron, certexpire_cron_job_t job, + void *data); + +#endif /** CERTEXPIRE_CRON_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/certexpire_export.c b/src/libcharon/plugins/certexpire/certexpire_export.c new file mode 100644 index 000000000..c73b0beda --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_export.c @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 "certexpire_export.h" + +#include "certexpire_cron.h" + +#include <time.h> +#include <limits.h> +#include <errno.h> + +#include <debug.h> +#include <utils/hashtable.h> +#include <threading/mutex.h> +#include <credentials/certificates/x509.h> + +typedef struct private_certexpire_export_t private_certexpire_export_t; + +/** + * Private data of an certexpire_export_t object. + */ +struct private_certexpire_export_t { + + /** + * Public certexpire_export_t interface. + */ + certexpire_export_t public; + + /** + * hashtable caching local trustchains, mapping entry_t => entry_t + */ + hashtable_t *local; + + /** + * hashtable caching remote trustchains, mapping entry_t => entry_t + */ + hashtable_t *remote; + + /** + * Mutex to lock hashtables + */ + mutex_t *mutex; + + /** + * Cronjob for export + */ + certexpire_cron_t *cron; + + /** + * strftime() format to generate local CSV file + */ + char *local_path; + + /** + * strftime() format to generate remote CSV file + */ + char *remote_path; + + /** + * stftime() format of the exported expiration date + */ + char *format; + + /** + * CSV field separator + */ + char *separator; + + /** + * TRUE to use fixed field count, CA at end + */ + bool fixed_fields; + + /** + * String to use in empty fields, if using fixed_fields + */ + char *empty_string; +}; + +/** + * Maximum number of expiration dates we store (for subject + IM CAs + CA) + */ +#define MAX_TRUSTCHAIN_LENGTH 7 + +/** + * Hashtable entry + */ +typedef struct { + /** certificate subject as subjectAltName or CN of a DN */ + char id[128]; + /** list of expiration dates, 0 if no certificate */ + time_t expire[MAX_TRUSTCHAIN_LENGTH]; +} entry_t; + +/** + * Hashtable hash function + */ +static u_int hash(entry_t *key) +{ + return chunk_hash(chunk_create(key->id, strlen(key->id))); +} + +/** + * Hashtable equals function + */ +static bool equals(entry_t *a, entry_t *b) +{ + return streq(a->id, b->id); +} + +/** + * Export a single trustchain to a path + */ +static void export_csv(private_certexpire_export_t *this, char *path, + hashtable_t *chains) +{ + enumerator_t *enumerator; + char buf[PATH_MAX]; + entry_t *entry; + FILE *file; + struct tm tm; + time_t t; + int i; + + t = time(NULL); + localtime_r(&t, &tm); + + strftime(buf, sizeof(buf), path, &tm); + file = fopen(buf, "a"); + if (file) + { + DBG1(DBG_CFG, "exporting expiration dates of %d trustchain%s to '%s'", + chains->get_count(chains), + chains->get_count(chains) == 1 ? "" : "s", buf); + this->mutex->lock(this->mutex); + enumerator = chains->create_enumerator(chains); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + fprintf(file, "%s%s", entry->id, this->separator); + for (i = 0; i < MAX_TRUSTCHAIN_LENGTH; i++) + { + if (entry->expire[i]) + { + localtime_r(&entry->expire[i], &tm); + strftime(buf, sizeof(buf), this->format, &tm); + fprintf(file, "%s", buf); + } + if (i == MAX_TRUSTCHAIN_LENGTH - 1) + { + fprintf(file, "\n"); + } + else if (entry->expire[i]) + { + fprintf(file, "%s", this->separator); + } + else if (this->fixed_fields) + { + fprintf(file, "%s%s", this->empty_string, this->separator); + } + } + chains->remove_at(chains, enumerator); + free(entry); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + fclose(file); + } + else + { + DBG1(DBG_CFG, "opening CSV file '%s' failed: %s", buf, strerror(errno)); + } +} + +/** + * Export cached trustchain expiration dates to CSV files + */ +static void cron_export(private_certexpire_export_t *this) +{ + if (this->local_path) + { + export_csv(this, this->local_path, this->local); + } + if (this->remote_path) + { + export_csv(this, this->remote_path, this->remote); + } +} + +METHOD(certexpire_export_t, add, void, + private_certexpire_export_t *this, linked_list_t *trustchain, bool local) +{ + enumerator_t *enumerator; + certificate_t *cert; + int count; + + /* don't store expiration dates if no path configured */ + if (local) + { + if (!this->local_path) + { + return; + } + } + else + { + if (!this->remote_path) + { + return; + } + } + + count = min(trustchain->get_count(trustchain), MAX_TRUSTCHAIN_LENGTH) - 1; + + enumerator = trustchain->create_enumerator(trustchain); + /* get subject cert */ + if (enumerator->enumerate(enumerator, &cert)) + { + identification_t *id; + entry_t *entry; + int i; + + INIT(entry); + + /* prefer FQDN subjectAltName... */ + if (cert->get_type(cert) == CERT_X509) + { + x509_t *x509 = (x509_t*)cert; + enumerator_t *sans; + + sans = x509->create_subjectAltName_enumerator(x509); + while (sans->enumerate(sans, &id)) + { + if (id->get_type(id) == ID_FQDN) + { + snprintf(entry->id, sizeof(entry->id), "%Y", id); + break; + } + } + sans->destroy(sans); + } + /* fallback to CN of DN */ + if (!entry->id[0]) + { + enumerator_t *parts; + id_part_t part; + chunk_t data; + + id = cert->get_subject(cert); + parts = id->create_part_enumerator(id); + while (parts->enumerate(parts, &part, &data)) + { + if (part == ID_PART_RDN_CN) + { + snprintf(entry->id, sizeof(entry->id), "%.*s", + (int)data.len, data.ptr); + break; + } + } + parts->destroy(parts); + } + /* no usable identity? skip */ + if (!entry->id[0]) + { + enumerator->destroy(enumerator); + free(entry); + return; + } + + /* get intermediate CA expiration dates */ + cert->get_validity(cert, NULL, NULL, &entry->expire[0]); + for (i = 1; i < count && enumerator->enumerate(enumerator, &cert); i++) + { + cert->get_validity(cert, NULL, NULL, &entry->expire[i]); + } + /* get CA expiration date, as last array entry */ + if (enumerator->enumerate(enumerator, &cert)) + { + cert->get_validity(cert, NULL, NULL, + &entry->expire[MAX_TRUSTCHAIN_LENGTH - 1]); + } + this->mutex->lock(this->mutex); + if (local) + { + entry = this->local->put(this->local, entry, entry); + } + else + { + entry = this->remote->put(this->remote, entry, entry); + } + this->mutex->unlock(this->mutex); + if (entry) + { + free(entry); + } + if (!this->cron) + { /* export directly if no cron job defined */ + if (local) + { + export_csv(this, this->local_path, this->local); + } + else + { + export_csv(this, this->remote_path, this->remote); + } + } + } + enumerator->destroy(enumerator); +} + +METHOD(certexpire_export_t, destroy, void, + private_certexpire_export_t *this) +{ + entry_t *key, *value; + enumerator_t *enumerator; + + enumerator = this->local->create_enumerator(this->local); + while (enumerator->enumerate(enumerator, &key, &value)) + { + free(value); + } + enumerator->destroy(enumerator); + enumerator = this->remote->create_enumerator(this->remote); + while (enumerator->enumerate(enumerator, &key, &value)) + { + free(value); + } + enumerator->destroy(enumerator); + + this->local->destroy(this->local); + this->remote->destroy(this->remote); + DESTROY_IF(this->cron); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +certexpire_export_t *certexpire_export_create() +{ + private_certexpire_export_t *this; + char *cron; + + INIT(this, + .public = { + .add = _add, + .destroy = _destroy, + }, + .local = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 4), + .remote = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 32), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .local_path = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.local", NULL), + .remote_path = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.remote", NULL), + .separator = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.separator", ","), + .format = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.format", "%d:%m:%Y"), + .fixed_fields = lib->settings->get_bool(lib->settings, + "charon.plugins.certexpire.csv.fixed_fields", TRUE), + .empty_string = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.empty_string", ""), + ); + + cron = lib->settings->get_str(lib->settings, + "charon.plugins.certexpire.csv.cron", NULL); + if (cron) + { + this->cron = certexpire_cron_create(cron, + (certexpire_cron_job_t)cron_export, this); + } + return &this->public; +} diff --git a/src/libcharon/plugins/certexpire/certexpire_export.h b/src/libcharon/plugins/certexpire/certexpire_export.h new file mode 100644 index 000000000..64281d0bd --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_export.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 certexpire_export certexpire_export + * @{ @ingroup certexpire + */ + +#ifndef CERTEXPIRE_EXPORT_H_ +#define CERTEXPIRE_EXPORT_H_ + +typedef struct certexpire_export_t certexpire_export_t; + +#include <utils/linked_list.h> + +/** + * Caches and exports trustchain information to CSV files. + */ +struct certexpire_export_t { + + /** + * Add trustchain to cache for export. + * + * @param trustchain trustchain, sorted list of certificate_t + * @param local TRUE for own chain, FALSE for remote chain + */ + void (*add)(certexpire_export_t *this, linked_list_t *trustchain, bool local); + + /** + * Destroy a certexpire_export_t. + */ + void (*destroy)(certexpire_export_t *this); +}; + +/** + * Create a certexpire_export instance. + */ +certexpire_export_t *certexpire_export_create(); + +#endif /** CERTEXPIRE_EXPORT_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/certexpire_listener.c b/src/libcharon/plugins/certexpire/certexpire_listener.c new file mode 100644 index 000000000..4c9c6ff3b --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_listener.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 "certexpire_listener.h" + +#include <daemon.h> + +typedef struct private_certexpire_listener_t private_certexpire_listener_t; + +/** + * Private data of an certexpire_listener_t object. + */ +struct private_certexpire_listener_t { + + /** + * Public certexpire_listener_t interface. + */ + certexpire_listener_t public; + + /** + * Export facility + */ + certexpire_export_t *export; +}; + +METHOD(listener_t, authorize, bool, + private_certexpire_listener_t *this, ike_sa_t *ike_sa, + bool final, bool *success) +{ + enumerator_t *rounds, *enumerator; + certificate_t *cert, *ca = NULL; + linked_list_t *trustchain; + auth_cfg_t *auth; + auth_rule_t rule; + + /* Check all rounds in final hook, as local authentication data are + * not completely available after round-invocation. */ + if (!final) + { + return TRUE; + } + + /* collect local certificates */ + trustchain = linked_list_create(); + rounds = ike_sa->create_auth_cfg_enumerator(ike_sa, TRUE); + while (rounds->enumerate(rounds, &auth)) + { + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + trustchain->insert_last(trustchain, cert); + + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_IM_CERT) + { + trustchain->insert_last(trustchain, cert); + } + if (rule == AUTH_RULE_CA_CERT) + { + /* the last CA cert is the one used in the trustchain. + * Previous CA certificates have been received as cert + * requests. */ + ca = cert; + } + } + enumerator->destroy(enumerator); + if (ca) + { + trustchain->insert_last(trustchain, ca); + } + } + } + rounds->destroy(rounds); + this->export->add(this->export, trustchain, TRUE); + trustchain->destroy(trustchain); + + /* collect remote certificates */ + trustchain = linked_list_create(); + rounds = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE); + while (rounds->enumerate(rounds, &auth)) + { + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + trustchain->insert_last(trustchain, cert); + + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_IM_CERT) + { + trustchain->insert_last(trustchain, cert); + } + } + enumerator->destroy(enumerator); + + cert = auth->get(auth, AUTH_RULE_CA_CERT); + if (cert) + { + trustchain->insert_last(trustchain, cert); + } + } + } + rounds->destroy(rounds); + this->export->add(this->export, trustchain, FALSE); + trustchain->destroy(trustchain); + return TRUE; +} + +METHOD(certexpire_listener_t, destroy, void, + private_certexpire_listener_t *this) +{ + free(this); +} + +/** + * See header + */ +certexpire_listener_t *certexpire_listener_create(certexpire_export_t *export) +{ + private_certexpire_listener_t *this; + + INIT(this, + .public = { + .listener = { + .authorize = _authorize, + }, + .destroy = _destroy, + }, + .export = export, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/certexpire/certexpire_listener.h b/src/libcharon/plugins/certexpire/certexpire_listener.h new file mode 100644 index 000000000..8601ff585 --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_listener.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 certexpire_listener certexpire_listener + * @{ @ingroup certexpire + */ + +#ifndef CERTEXPIRE_LISTENER_H_ +#define CERTEXPIRE_LISTENER_H_ + +#include <bus/listeners/listener.h> + +#include "certexpire_export.h" + +typedef struct certexpire_listener_t certexpire_listener_t; + +/** + * Listener collecting certificate expire information after authentication. + */ +struct certexpire_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a certexpire_listener_t. + */ + void (*destroy)(certexpire_listener_t *this); +}; + +/** + * Create a certexpire_listener instance. + * + * @param export facility exporting collected trustchains + * @return listener instance + */ +certexpire_listener_t *certexpire_listener_create(certexpire_export_t *export); + +#endif /** CERTEXPIRE_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/certexpire_plugin.c b/src/libcharon/plugins/certexpire/certexpire_plugin.c new file mode 100644 index 000000000..2b4c0b68b --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_plugin.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 "certexpire_plugin.h" + +#include "certexpire_listener.h" +#include "certexpire_export.h" + +#include <daemon.h> + +typedef struct private_certexpire_plugin_t private_certexpire_plugin_t; + +/** + * Private data of certexpire plugin + */ +struct private_certexpire_plugin_t { + + /** + * Implements plugin interface + */ + certexpire_plugin_t public; + + /** + * Listener collecting expire information + */ + certexpire_listener_t *listener; + + /** + * Cache and export trustchain expire information + */ + certexpire_export_t *export; +}; + +METHOD(plugin_t, get_name, char*, + private_certexpire_plugin_t *this) +{ + return "certexpire"; +} + +METHOD(plugin_t, destroy, void, + private_certexpire_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + this->export->destroy(this->export); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *certexpire_plugin_create() +{ + private_certexpire_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .export = certexpire_export_create(), + ); + this->listener = certexpire_listener_create(this->export), + charon->bus->add_listener(charon->bus, &this->listener->listener); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/certexpire/certexpire_plugin.h b/src/libcharon/plugins/certexpire/certexpire_plugin.h new file mode 100644 index 000000000..bcb5606f5 --- /dev/null +++ b/src/libcharon/plugins/certexpire/certexpire_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 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 certexpire certexpire + * @ingroup cplugins + * + * @defgroup certexpire_plugin certexpire_plugin + * @{ @ingroup certexpire + */ + +#ifndef CERTEXPIRE_PLUGIN_H_ +#define CERTEXPIRE_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct certexpire_plugin_t certexpire_plugin_t; + +/** + * Plugin exporting expiration dates of used certificates to CSV files. + */ +struct certexpire_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** CERTEXPIRE_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in index a3104e4c0..df4420b04 100644 --- a/src/libcharon/plugins/coupling/Makefile.in +++ b/src/libcharon/plugins/coupling/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index 7853659df..089afd39d 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,6 +203,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -216,11 +220,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c index c98d50554..5d98e5b8d 100644 --- a/src/libcharon/plugins/dhcp/dhcp_socket.c +++ b/src/libcharon/plugins/dhcp/dhcp_socket.c @@ -760,8 +760,8 @@ dhcp_socket_t *dhcp_socket_create() return NULL; } - this->job = callback_job_create((callback_job_cb_t)receive_dhcp, - this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)receive_dhcp, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); return &this->public; diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in index 8cffa2f10..87984a182 100644 --- a/src/libcharon/plugins/duplicheck/Makefile.in +++ b/src/libcharon/plugins/duplicheck/Makefile.in @@ -202,6 +202,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -210,6 +213,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -226,11 +230,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -274,6 +280,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/duplicheck/duplicheck_notify.c b/src/libcharon/plugins/duplicheck/duplicheck_notify.c index 4e7618235..b86f1ef3d 100644 --- a/src/libcharon/plugins/duplicheck/duplicheck_notify.c +++ b/src/libcharon/plugins/duplicheck/duplicheck_notify.c @@ -203,8 +203,8 @@ duplicheck_notify_t *duplicheck_notify_create() destroy(this); return NULL; } - this->job = callback_job_create((callback_job_cb_t)receive, - this, NULL, NULL); + 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; diff --git a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c index 5bc1a14af..df28e7f12 100644 --- a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c +++ b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c @@ -66,7 +66,7 @@ plugin_t *duplicheck_plugin_create() private_duplicheck_plugin_t *this; if (!lib->settings->get_bool(lib->settings, - "charon.plugins.duplicheck.enabled", TRUE)) + "charon.plugins.duplicheck.enable", TRUE)) { return NULL; } diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index 666e22957..e7a3d780a 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c index df0c4c5b4..8c392405e 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c @@ -20,6 +20,7 @@ #include <simaka_message.h> #include <simaka_crypto.h> +#include <simaka_manager.h> typedef struct private_eap_aka_peer_t private_eap_aka_peer_t; @@ -34,6 +35,11 @@ struct private_eap_aka_peer_t { eap_aka_peer_t public; /** + * AKA backend manager + */ + simaka_manager_t *mgr; + + /** * EAP-AKA crypto helper */ simaka_crypto_t *crypto; @@ -91,7 +97,7 @@ static eap_payload_t* create_client_error(private_eap_aka_peer_t *this) encoded = htons(AKA_UNABLE_TO_PROCESS); message->add_attribute(message, AT_CLIENT_ERROR_CODE, chunk_create((char*)&encoded, sizeof(encoded))); - out = message->generate(message, chunk_empty); + out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); return out; } @@ -140,7 +146,7 @@ static status_t process_identity(private_eap_aka_peer_t *this, switch (id_req) { case AT_ANY_ID_REQ: - this->reauth = charon->sim->card_get_reauth(charon->sim, + this->reauth = this->mgr->card_get_reauth(this->mgr, this->permanent, this->mk, &this->counter); if (this->reauth) { @@ -149,8 +155,8 @@ static status_t process_identity(private_eap_aka_peer_t *this, } /* FALL */ case AT_FULLAUTH_ID_REQ: - this->pseudonym = charon->sim->card_get_pseudonym(charon->sim, - this->permanent); + this->pseudonym = this->mgr->card_get_pseudonym(this->mgr, + this->permanent); if (this->pseudonym) { id = this->pseudonym->get_encoding(this->pseudonym); @@ -169,7 +175,7 @@ static status_t process_identity(private_eap_aka_peer_t *this, { message->add_attribute(message, AT_IDENTITY, id); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); return NEED_MORE; @@ -220,10 +226,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, return NEED_MORE; } - status = charon->sim->card_get_quintuplet(charon->sim, this->permanent, + status = this->mgr->card_get_quintuplet(this->mgr, this->permanent, rand.ptr, autn.ptr, ck, ik, res, &res_len); if (status == INVALID_STATE && - charon->sim->card_resync(charon->sim, this->permanent, rand.ptr, auts)) + this->mgr->card_resync(this->mgr, this->permanent, rand.ptr, auts)) { DBG1(DBG_IKE, "received SQN invalid, sending %N", simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE); @@ -231,7 +237,8 @@ static status_t process_challenge(private_eap_aka_peer_t *this, AKA_SYNCHRONIZATION_FAILURE, this->crypto); message->add_attribute(message, AT_AUTS, chunk_create(auts, AKA_AUTS_LEN)); - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, + chunk_empty)); message->destroy(message); return NEED_MORE; } @@ -241,7 +248,8 @@ static status_t process_challenge(private_eap_aka_peer_t *this, this->permanent, simaka_subtype_names, AKA_AUTHENTICATION_REJECT); message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA, AKA_AUTHENTICATION_REJECT, this->crypto); - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, + chunk_empty)); message->destroy(message); return NEED_MORE; } @@ -274,13 +282,13 @@ static status_t process_challenge(private_eap_aka_peer_t *this, case AT_NEXT_REAUTH_ID: this->counter = 0; id = identification_create_from_data(data); - charon->sim->card_set_reauth(charon->sim, this->permanent, id, - this->mk, this->counter); + this->mgr->card_set_reauth(this->mgr, this->permanent, id, + this->mk, this->counter); id->destroy(id); break; case AT_NEXT_PSEUDONYM: id = identification_create_from_data(data); - charon->sim->card_set_pseudonym(charon->sim, this->permanent, id); + this->mgr->card_set_pseudonym(this->mgr, this->permanent, id); id->destroy(id); break; default: @@ -292,7 +300,7 @@ static status_t process_challenge(private_eap_aka_peer_t *this, message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_CHALLENGE, this->crypto); message->add_attribute(message, AT_RES, chunk_create(res, res_len)); - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); return NEED_MORE; } @@ -389,13 +397,13 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, identification_t *reauth; reauth = identification_create_from_data(data); - charon->sim->card_set_reauth(charon->sim, this->permanent, reauth, - this->mk, this->counter); + this->mgr->card_set_reauth(this->mgr, this->permanent, reauth, + this->mk, this->counter); reauth->destroy(reauth); } } message->add_attribute(message, AT_COUNTER, counter); - *out = message->generate(message, nonce); + *out = eap_payload_create_data_own(message->generate(message, nonce)); message->destroy(message); return NEED_MORE; } @@ -446,7 +454,8 @@ static status_t process_notification(private_eap_aka_peer_t *this, { /* empty notification reply */ message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_NOTIFICATION, this->crypto); - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, + chunk_empty)); message->destroy(message); } else @@ -466,7 +475,7 @@ METHOD(eap_method_t, process, status_t, /* store received EAP message identifier */ this->identifier = in->get_identifier(in); - message = simaka_message_create_from_payload(in, this->crypto); + message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { *out = create_client_error(this); @@ -578,7 +587,8 @@ eap_aka_peer_t *eap_aka_peer_create(identification_t *server, .destroy = _destroy, }, }, - .crypto = simaka_crypto_create(), + .crypto = simaka_crypto_create(EAP_AKA), + .mgr = lib->get(lib, "aka-manager"), ); if (!this->crypto) diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.h b/src/libcharon/plugins/eap_aka/eap_aka_peer.h index 65a210406..974ba2721 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_peer.h +++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.h @@ -26,7 +26,7 @@ typedef struct eap_aka_peer_t eap_aka_peer_t; #include <sa/authenticators/eap/eap_method.h> /** - * Implementation of the eap_method_t interface using EAP-AKA as a client. + * EAP-AKA peer implementation. */ struct eap_aka_peer_t { diff --git a/src/libcharon/plugins/eap_aka/eap_aka_plugin.c b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c index 394a14b59..83805d727 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_plugin.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c @@ -19,20 +19,61 @@ #include "eap_aka_server.h" #include <daemon.h> +#include <simaka_manager.h> + +typedef struct private_eap_aka_plugin_t private_eap_aka_plugin_t; + +/** + * Private data of an eap_sim_plugin_t object. + */ +struct private_eap_aka_plugin_t { + + /** + * Public interface. + */ + eap_aka_plugin_t public; + + /** + * EAP-AKA backend manager + */ + simaka_manager_t *mgr; +}; METHOD(plugin_t, get_name, char*, - eap_aka_plugin_t *this) + private_eap_aka_plugin_t *this) { return "eap-aka"; } +METHOD(plugin_t, get_features, int, + private_eap_aka_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_PROVIDE(CUSTOM, "aka-manager"), + PLUGIN_CALLBACK(eap_method_register, eap_aka_server_create), + PLUGIN_PROVIDE(EAP_SERVER, EAP_AKA), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(PRF, PRF_FIPS_SHA1_160), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_SHA1_128), + PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16), + PLUGIN_CALLBACK(eap_method_register, eap_aka_peer_create), + PLUGIN_PROVIDE(EAP_PEER, EAP_AKA), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(PRF, PRF_FIPS_SHA1_160), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_SHA1_128), + PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, - eap_aka_plugin_t *this) + private_eap_aka_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_aka_server_create); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_aka_peer_create); + lib->set(lib, "aka-manager", NULL); + this->mgr->destroy(this->mgr); free(this); } @@ -41,21 +82,19 @@ METHOD(plugin_t, destroy, void, */ plugin_t *eap_aka_plugin_create() { - eap_aka_plugin_t *this; + private_eap_aka_plugin_t *this; INIT(this, - .plugin = { - .get_name = _get_name, - .reload = (void*)return_false, - .destroy = _destroy, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, }, + .mgr = simaka_manager_create(), ); + lib->set(lib, "aka-manager", this->mgr); - charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_SERVER, - (eap_constructor_t)eap_aka_server_create); - charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_PEER, - (eap_constructor_t)eap_aka_peer_create); - - return &this->plugin; + return &this->public.plugin; } - diff --git a/src/libcharon/plugins/eap_aka/eap_aka_plugin.h b/src/libcharon/plugins/eap_aka/eap_aka_plugin.h index d011904b3..8d4fbadfa 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_plugin.h +++ b/src/libcharon/plugins/eap_aka/eap_aka_plugin.h @@ -33,6 +33,11 @@ typedef struct eap_aka_plugin_t eap_aka_plugin_t; * * EAP-AKA uses 3rd generation mobile phone standard authentication * mechanism for authentication, as defined RFC4187. + * + * This plugin implements the protocol level of EAP-AKA and uses simaka_card_t + * and simaka_provider_t backends to provide triplets. It registers a + * simaka_manager_t on the library as "aka-manager", other plugins can use it + * to provide the required backends. */ struct eap_aka_plugin_t { diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c index bf0020ad8..d8e85ceef 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_server.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c @@ -20,6 +20,7 @@ #include <simaka_message.h> #include <simaka_crypto.h> +#include <simaka_manager.h> /** length of the AT_NONCE_S value */ #define NONCE_LEN 16 @@ -37,6 +38,11 @@ struct private_eap_aka_server_t { eap_aka_server_t public; /** + * AKA backend manager + */ + simaka_manager_t *mgr; + + /** * EAP-AKA crypto helper */ simaka_crypto_t *crypto; @@ -133,7 +139,7 @@ static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out) { message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); this->pending = AKA_IDENTITY; @@ -152,7 +158,7 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out) chunk_t data, mk; identification_t *id; - if (!charon->sim->provider_get_quintuplet(charon->sim, this->permanent, + if (!this->mgr->provider_get_quintuplet(this->mgr, this->permanent, rand, xres, &xres_len, ck, ik, autn)) { if (this->use_pseudonym) @@ -183,24 +189,21 @@ static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out) AKA_CHALLENGE, this->crypto); message->add_attribute(message, AT_RAND, this->rand); message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN)); - id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr); + id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr); if (id) { message->add_attribute(message, AT_NEXT_REAUTH_ID, id->get_encoding(id)); id->destroy(id); } - else + id = this->mgr->provider_gen_pseudonym(this->mgr, this->permanent); + if (id) { - id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent); - if (id) - { - message->add_attribute(message, AT_NEXT_PSEUDONYM, - id->get_encoding(id)); - id->destroy(id); - } + message->add_attribute(message, AT_NEXT_PSEUDONYM, + id->get_encoding(id)); + id->destroy(id); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); free(mk.ptr); @@ -237,14 +240,14 @@ static status_t reauthenticate(private_eap_aka_server_t *this, AKA_REAUTHENTICATION, this->crypto); message->add_attribute(message, AT_COUNTER, this->counter); message->add_attribute(message, AT_NONCE_S, this->nonce); - next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk); + next = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk); if (next) { message->add_attribute(message, AT_NEXT_REAUTH_ID, next->get_encoding(next)); next->destroy(next); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); this->pending = SIM_REAUTHENTICATION; @@ -310,8 +313,7 @@ static status_t process_identity(private_eap_aka_server_t *this, char mk[HASH_SIZE_SHA1]; u_int16_t counter; - permanent = charon->sim->provider_is_reauth(charon->sim, id, - mk, &counter); + permanent = this->mgr->provider_is_reauth(this->mgr, id, mk, &counter); if (permanent) { this->permanent->destroy(this->permanent); @@ -325,7 +327,7 @@ static status_t process_identity(private_eap_aka_server_t *this, } if (this->use_pseudonym) { - permanent = charon->sim->provider_is_pseudonym(charon->sim, id); + permanent = this->mgr->provider_is_pseudonym(this->mgr, id); if (permanent) { this->permanent->destroy(this->permanent); @@ -506,8 +508,8 @@ static status_t process_synchronize(private_eap_aka_server_t *this, return FAILED; } - if (!charon->sim->provider_resync(charon->sim, this->permanent, - this->rand.ptr, auts.ptr)) + if (!this->mgr->provider_resync(this->mgr, this->permanent, + this->rand.ptr, auts.ptr)) { DBG1(DBG_IKE, "no AKA provider found supporting " "resynchronization for '%Y'", this->permanent); @@ -564,7 +566,7 @@ METHOD(eap_method_t, process, status_t, simaka_message_t *message; status_t status; - message = simaka_message_create_from_payload(in, this->crypto); + message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { return FAILED; @@ -676,7 +678,8 @@ eap_aka_server_t *eap_aka_server_create(identification_t *server, .destroy = _destroy, }, }, - .crypto = simaka_crypto_create(), + .crypto = simaka_crypto_create(EAP_AKA), + .mgr = lib->get(lib, "aka-manager"), ); if (!this->crypto) diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.h b/src/libcharon/plugins/eap_aka/eap_aka_server.h index d48fc4c34..5ab1c4dfd 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_server.h +++ b/src/libcharon/plugins/eap_aka/eap_aka_server.h @@ -26,7 +26,7 @@ typedef struct eap_aka_server_t eap_aka_server_t; #include <sa/authenticators/eap/eap_method.h> /** - * Implementation of the eap_method_t interface using EAP-AKA as server. + * EAP-AKA server implementation. */ struct eap_aka_server_t { diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am index 598799e2a..b4d6dc1d2 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am @@ -1,13 +1,17 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic +libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp + if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la else plugin_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la +libstrongswan_eap_aka_3gpp2_la_LIBADD += $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_aka_3gpp2_la_SOURCES = \ @@ -15,6 +19,3 @@ libstrongswan_eap_aka_3gpp2_la_SOURCES = \ eap_aka_3gpp2_card.h eap_aka_3gpp2_card.c \ eap_aka_3gpp2_provider.h eap_aka_3gpp2_provider.c \ eap_aka_3gpp2_functions.h eap_aka_3gpp2_functions.c - -libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version -libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index 1fe86a2bb..b0890fb39 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -34,6 +34,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libsimaka/libsimaka.la subdir = src/libcharon/plugins/eap_aka_3gpp2 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -74,7 +75,7 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_aka_3gpp2_la_DEPENDENCIES = +libstrongswan_eap_aka_3gpp2_la_DEPENDENCIES = $(am__append_1) am_libstrongswan_eap_aka_3gpp2_la_OBJECTS = eap_aka_3gpp2_plugin.lo \ eap_aka_3gpp2_card.lo eap_aka_3gpp2_provider.lo \ eap_aka_3gpp2_functions.lo @@ -196,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -279,9 +287,11 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic +libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp $(am__append_1) @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-aka-3gpp2.la libstrongswan_eap_aka_3gpp2_la_SOURCES = \ @@ -290,8 +300,6 @@ libstrongswan_eap_aka_3gpp2_la_SOURCES = \ eap_aka_3gpp2_provider.h eap_aka_3gpp2_provider.c \ eap_aka_3gpp2_functions.h eap_aka_3gpp2_functions.c -libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version -libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp all: all-am .SUFFIXES: diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c index 5c0fe38ad..cec06fbd7 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c @@ -51,14 +51,10 @@ struct private_eap_aka_3gpp2_card_t { bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN]); void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset); -/** - * Implementation of sim_card_t.get_quintuplet - */ -static status_t get_quintuplet(private_eap_aka_3gpp2_card_t *this, - identification_t *id, char rand[AKA_RAND_LEN], - char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], - char ik[AKA_IK_LEN], char res[AKA_RES_MAX], - int *res_len) +METHOD(simaka_card_t, get_quintuplet, status_t, + private_eap_aka_3gpp2_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) { char *amf, *mac; char k[AKA_K_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN], xmac[AKA_MAC_LEN]; @@ -112,11 +108,9 @@ static status_t get_quintuplet(private_eap_aka_3gpp2_card_t *this, return SUCCESS; } -/** - * Implementation of sim_card_t.resync - */ -static bool resync(private_eap_aka_3gpp2_card_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) +METHOD(simaka_card_t, resync, bool, + private_eap_aka_3gpp2_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) { char amf[AKA_AMF_LEN], k[AKA_K_LEN], aks[AKA_AK_LEN], macs[AKA_MAC_LEN]; @@ -138,10 +132,8 @@ static bool resync(private_eap_aka_3gpp2_card_t *this, identification_t *id, return TRUE; } -/** - * Implementation of eap_aka_3gpp2_card_t.destroy. - */ -static void destroy(private_eap_aka_3gpp2_card_t *this) +METHOD(eap_aka_3gpp2_card_t, destroy, void, + private_eap_aka_3gpp2_card_t *this) { free(this); } @@ -151,25 +143,30 @@ static void destroy(private_eap_aka_3gpp2_card_t *this) */ eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f) { - private_eap_aka_3gpp2_card_t *this = malloc_thing(private_eap_aka_3gpp2_card_t); - - this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false; - this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet; - this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))resync; - this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *id))return_null; - this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop; - this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop; - this->public.destroy = (void(*)(eap_aka_3gpp2_card_t*))destroy; - - this->f = f; - this->seq_check = lib->settings->get_bool(lib->settings, + private_eap_aka_3gpp2_card_t *this; + + INIT(this, + .public = { + .card = { + .get_triplet = (void*)return_false, + .get_quintuplet = _get_quintuplet, + .resync = _resync, + .get_pseudonym = (void*)return_null, + .set_pseudonym = (void*)nop, + .get_reauth = (void*)return_null, + .set_reauth = (void*)nop, + }, + .destroy = _destroy, + }, + .f = f, + .seq_check = lib->settings->get_bool(lib->settings, "charon.plugins.eap-aka-3gpp2.seq_check", #ifdef SEQ_CHECK /* handle legacy compile time configuration as default */ - TRUE); + TRUE), #else /* !SEQ_CHECK */ - FALSE); + FALSE), #endif /* SEQ_CHECK */ + ); eap_aka_3gpp2_get_sqn(this->sqn, 0); diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h index b95bc52af..eb6b1f75f 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.h @@ -23,7 +23,7 @@ #include "eap_aka_3gpp2_functions.h" -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_card.h> typedef struct eap_aka_3gpp2_card_t eap_aka_3gpp2_card_t; @@ -33,9 +33,9 @@ typedef struct eap_aka_3gpp2_card_t eap_aka_3gpp2_card_t; struct eap_aka_3gpp2_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_aka_3gpp2_card_t. diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c index 1d3d246d1..d000bebbb 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.c @@ -284,9 +284,10 @@ static void f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN], /** * Calculate MAC from RAND, SQN, AMF using K */ -static void f1(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], - u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f1, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], + u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]) { f1x(this->prf, F1, k, rand, sqn, amf, mac); DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN); @@ -295,9 +296,10 @@ static void f1(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate MACS from RAND, SQN, AMF using K */ -static void f1star(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], - u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f1star, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], + u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]) { f1x(this->prf, F1STAR, k, rand, sqn, amf, macs); DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN); @@ -306,8 +308,9 @@ static void f1star(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate RES from RAND using K */ -static void f2(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]) +METHOD(eap_aka_3gpp2_functions_t, f2, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]) { fx(this->prf, F2, k, rand, res); DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX); @@ -316,8 +319,9 @@ static void f2(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate CK from RAND using K */ -static void f3(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f3, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]) { fx(this->prf, F3, k, rand, ck); DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN); @@ -326,8 +330,9 @@ static void f3(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate IK from RAND using K */ -static void f4(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f4, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]) { fx(this->prf, F4, k, rand, ik); DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN); @@ -336,8 +341,9 @@ static void f4(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate AK from a RAND using K */ -static void f5(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f5, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]) { f5x(this->prf, F5, k, rand, ak); DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN); @@ -346,18 +352,16 @@ static void f5(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], /** * Calculate AKS from a RAND using K */ -static void f5star(private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], - u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]) +METHOD(eap_aka_3gpp2_functions_t, f5star, void, + private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], + u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]) { f5x(this->prf, F5STAR, k, rand, aks); DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN); } - -/** - * Implementation of eap_aka_3gpp2_functions_t.destroy. - */ -static void destroy(private_eap_aka_3gpp2_functions_t *this) +METHOD(eap_aka_3gpp2_functions_t, destroy, void, + private_eap_aka_3gpp2_functions_t *this) { this->prf->destroy(this->prf); free(this); @@ -370,18 +374,19 @@ eap_aka_3gpp2_functions_t *eap_aka_3gpp2_functions_create() { private_eap_aka_3gpp2_functions_t *this; - this = malloc_thing(private_eap_aka_3gpp2_functions_t); - - this->public.f1 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN]))f1; - this->public.f1star = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN], u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN]))f1star; - this->public.f2 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX]))f2; - this->public.f3 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN]))f3; - this->public.f4 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN]))f4; - this->public.f5 = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN]))f5; - this->public.f5star = (void(*)(eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN], u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN]))f5star; - this->public.destroy = (void(*)(eap_aka_3gpp2_functions_t*))destroy; - - this->prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1); + INIT(this, + .public = { + .f1 = _f1, + .f1star = _f1star, + .f2 = _f2, + .f3 = _f3, + .f4 = _f4, + .f5 = _f5, + .f5star = _f5star, + .destroy = _destroy, + }, + .prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1), + ); if (!this->prf) { DBG1(DBG_CFG, "%N not supported, unable to use 3GPP2 algorithm", diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h index 95c6da6a9..855efec3e 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.h @@ -21,7 +21,7 @@ #ifndef EAP_AKA_3GPP2_FUNCTIONS_H_ #define EAP_AKA_3GPP2_FUNCTIONS_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_manager.h> #define AKA_SQN_LEN 6 #define AKA_K_LEN 16 diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c index ef5f62e34..d7d0d0507 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c @@ -54,14 +54,71 @@ METHOD(plugin_t, get_name, char*, return "eap-aka-3gpp2"; } -METHOD(plugin_t, destroy, void, - private_eap_aka_3gpp2_t *this) +/** + * Try to instanciate 3gpp2 functions and card/provider backends + */ +static bool register_functions(private_eap_aka_3gpp2_t *this, + plugin_feature_t *feature, bool reg, void *data) { - charon->sim->remove_card(charon->sim, &this->card->card); - charon->sim->remove_provider(charon->sim, &this->provider->provider); + if (reg) + { + this->functions = eap_aka_3gpp2_functions_create(); + if (!this->functions) + { + return FALSE; + } + this->card = eap_aka_3gpp2_card_create(this->functions); + this->provider = eap_aka_3gpp2_provider_create(this->functions); + return TRUE; + } this->card->destroy(this->card); this->provider->destroy(this->provider); this->functions->destroy(this->functions); + this->card = NULL; + this->provider = NULL; + this->functions = NULL; + return TRUE; +} + +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_aka_3gpp2_t *this) +{ + return &this->card->card; +} + +/** + * Callback providing our provider to register + */ +static simaka_provider_t* get_provider(private_eap_aka_3gpp2_t *this) +{ + return &this->provider->provider; +} + +METHOD(plugin_t, get_features, int, + private_eap_aka_3gpp2_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((void*)register_functions, NULL), + PLUGIN_PROVIDE(CUSTOM, "eap-aka-3gpp2-functions"), + PLUGIN_DEPENDS(PRF, PRF_KEYED_SHA1), + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "aka-card"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-aka-3gpp2-functions"), + PLUGIN_CALLBACK(simaka_manager_register, get_provider), + PLUGIN_PROVIDE(CUSTOM, "aka-provider"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-aka-3gpp2-functions"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_eap_aka_3gpp2_t *this) +{ free(this); } @@ -76,24 +133,12 @@ plugin_t *eap_aka_3gpp2_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .functions = eap_aka_3gpp2_functions_create(), ); - if (!this->functions) - { - free(this); - return NULL; - } - this->card = eap_aka_3gpp2_card_create(this->functions); - this->provider = eap_aka_3gpp2_provider_create(this->functions); - - charon->sim->add_card(charon->sim, &this->card->card); - charon->sim->add_provider(charon->sim, &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c index a9767ad91..b2b43da2a 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c @@ -80,14 +80,10 @@ void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset) memcpy(sqn + 4, &time.tv_usec, 2); } -/** - * Implementation of usim_provider_t.get_quintuplet - */ -static bool get_quintuplet(private_eap_aka_3gpp2_provider_t *this, - identification_t *id, char rand[AKA_RAND_LEN], - char xres[AKA_RES_MAX], int *xres_len, - char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], - char autn[AKA_AUTN_LEN]) +METHOD(simaka_provider_t, get_quintuplet, bool, + private_eap_aka_3gpp2_provider_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, + char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]) { rng_t *rng; char mac[AKA_MAC_LEN], ak[AKA_AK_LEN], k[AKA_K_LEN]; @@ -131,12 +127,9 @@ static bool get_quintuplet(private_eap_aka_3gpp2_provider_t *this, return TRUE; } -/** - * Implementation of usim_provider_t.resync - */ -static bool resync(private_eap_aka_3gpp2_provider_t *this, - identification_t *id, char rand[AKA_RAND_LEN], - char auts[AKA_AUTS_LEN]) +METHOD(simaka_provider_t, resync, bool, + private_eap_aka_3gpp2_provider_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) { char *sqn, *macs; char aks[AKA_AK_LEN], k[AKA_K_LEN], amf[AKA_AMF_LEN], xmacs[AKA_MAC_LEN]; @@ -169,10 +162,8 @@ static bool resync(private_eap_aka_3gpp2_provider_t *this, return TRUE; } -/** - * Implementation of eap_aka_3gpp2_provider_t.destroy. - */ -static void destroy(private_eap_aka_3gpp2_provider_t *this) +METHOD(eap_aka_3gpp2_provider_t, destroy, void, + private_eap_aka_3gpp2_provider_t *this) { free(this); } @@ -183,18 +174,23 @@ static void destroy(private_eap_aka_3gpp2_provider_t *this) eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create( eap_aka_3gpp2_functions_t *f) { - private_eap_aka_3gpp2_provider_t *this = malloc_thing(private_eap_aka_3gpp2_provider_t); - - this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false; - this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))get_quintuplet; - this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))resync; - this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null; - this->public.destroy = (void(*)(eap_aka_3gpp2_provider_t*))destroy; - - this->f = f; + private_eap_aka_3gpp2_provider_t *this; + + INIT(this, + .public = { + .provider = { + .get_triplet = (void*)return_false, + .get_quintuplet = _get_quintuplet, + .resync = _resync, + .is_pseudonym = (void*)return_null, + .gen_pseudonym = (void*)return_null, + .is_reauth = (void*)return_null, + .gen_reauth = (void*)return_null, + }, + .destroy = _destroy, + }, + .f = f, + ); /* use an offset to accept clock skew between client/server without resync */ eap_aka_3gpp2_get_sqn(this->sqn, 180); diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h index 22ac0a96e..0e1af8554 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.h @@ -23,7 +23,7 @@ #include "eap_aka_3gpp2_functions.h" -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_provider.h> typedef struct eap_aka_3gpp2_provider_t eap_aka_3gpp2_provider_t; @@ -33,9 +33,9 @@ typedef struct eap_aka_3gpp2_provider_t eap_aka_3gpp2_provider_t; struct eap_aka_3gpp2_provider_t { /** - * Implements sim_provider_t interface. + * Implements simaka_provider_t interface. */ - sim_provider_t provider; + simaka_provider_t provider; /** * Destroy a eap_aka_3gpp2_provider_t. diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 4f555a982..b3f989e38 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -193,6 +193,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -201,6 +204,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -217,11 +221,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +271,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c index c40ce60eb..bd70b757a 100644 --- a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c +++ b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c @@ -28,13 +28,22 @@ METHOD(plugin_t, get_name, char*, return "eap-gtc"; } +METHOD(plugin_t, get_features, int, + eap_gtc_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_gtc_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_GTC), + PLUGIN_CALLBACK(eap_method_register, eap_gtc_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_GTC), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_gtc_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_gtc_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_gtc_create_peer); free(this); } @@ -48,7 +57,7 @@ plugin_t *eap_gtc_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index 9dc4602ff..b348b5fb5 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_identity/eap_identity_plugin.c b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c index 3297416b2..b09e51568 100644 --- a/src/libcharon/plugins/eap_identity/eap_identity_plugin.c +++ b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c @@ -24,13 +24,22 @@ METHOD(plugin_t, get_name, char*, return "eap-identity"; } +METHOD(plugin_t, get_features, int, + eap_identity_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_identity_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_IDENTITY), + PLUGIN_CALLBACK(eap_method_register, eap_identity_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_IDENTITY), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_identity_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_identity_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_identity_create_peer); free(this); } @@ -44,16 +53,11 @@ plugin_t *eap_identity_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_SERVER, - (eap_constructor_t)eap_identity_create_server); - charon->eap->add_method(charon->eap, EAP_IDENTITY, 0, EAP_PEER, - (eap_constructor_t)eap_identity_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index e828fbc3e..209753b2d 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -193,6 +193,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -201,6 +204,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -217,11 +221,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +271,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_md5/eap_md5_plugin.c b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c index fe5ae51bf..d045e02bf 100644 --- a/src/libcharon/plugins/eap_md5/eap_md5_plugin.c +++ b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c @@ -24,13 +24,26 @@ METHOD(plugin_t, get_name, char*, return "eap-md5"; } +METHOD(plugin_t, get_features, int, + eap_md5_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_md5_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_MD5), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(eap_method_register, eap_md5_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_MD5), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_md5_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_md5_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_md5_create_peer); free(this); } @@ -44,16 +57,11 @@ plugin_t *eap_md5_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_SERVER, - (eap_constructor_t)eap_md5_create_server); - charon->eap->add_method(charon->eap, EAP_MD5, 0, EAP_PEER, - (eap_constructor_t)eap_md5_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index 4986fdce3..6d3d7f8db 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c index 1dd94f6fb..9dfc69205 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c @@ -814,7 +814,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, eap_mschapv2_header_t *eap; chunk_t data; char *message, *token, *msg = NULL; - int message_len, error = 0, retriable; + int message_len, error = 0; chunk_t challenge = chunk_empty; data = in->get_data(in); @@ -842,8 +842,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, } else if (strneq(token, "R=", 2)) { - token += 2; - retriable = atoi(token); + /* ignore retriable */ } else if (strneq(token, "C=", 2)) { @@ -860,9 +859,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, } else if (strneq(token, "V=", 2)) { - int version; - token += 2; - version = atoi(token); + /* ignore version */ } else if (strneq(token, "M=", 2)) { diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c index e809b14b6..6fd96708a 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c @@ -25,13 +25,30 @@ METHOD(plugin_t, get_name, char*, return "eap-mschapv2"; } +METHOD(plugin_t, get_features, int, + eap_mschapv2_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_mschapv2_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_MSCHAPV2), + PLUGIN_DEPENDS(CRYPTER, ENCR_DES_ECB, 8), + PLUGIN_DEPENDS(HASHER, HASH_MD4), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(eap_method_register, eap_mschapv2_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_MSCHAPV2), + PLUGIN_DEPENDS(CRYPTER, ENCR_DES_ECB, 8), + PLUGIN_DEPENDS(HASHER, HASH_MD4), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_mschapv2_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_mschapv2_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_mschapv2_create_peer); free(this); } @@ -45,16 +62,11 @@ plugin_t *eap_mschapv2_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_MSCHAPV2, 0, EAP_SERVER, - (eap_constructor_t)eap_mschapv2_create_server); - charon->eap->add_method(charon->eap, EAP_MSCHAPV2, 0, EAP_PEER, - (eap_constructor_t)eap_mschapv2_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in index 0ed4a3dcf..4f860e175 100644 --- a/src/libcharon/plugins/eap_peap/Makefile.in +++ b/src/libcharon/plugins/eap_peap/Makefile.in @@ -196,6 +196,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +207,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +224,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +274,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_peap/eap_peap.c b/src/libcharon/plugins/eap_peap/eap_peap.c index 5bae0fa9b..bd426bba7 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap.c +++ b/src/libcharon/plugins/eap_peap/eap_peap.c @@ -166,7 +166,8 @@ static eap_peap_t *eap_peap_create(private_eap_peap_t * this, "charon.plugins.eap-peap.max_message_count", MAX_MESSAGE_COUNT); include_length = lib->settings->get_bool(lib->settings, "charon.plugins.eap-peap.include_length", FALSE); - tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_PEAP, application); + tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_PEAP, + application, NULL); this->tls_eap = tls_eap_create(EAP_PEAP, tls, frag_size, max_msg_count, include_length); if (!this->tls_eap) diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.c b/src/libcharon/plugins/eap_peap/eap_peap_avp.c index 06e5222d9..10f6ec11c 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_avp.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.c @@ -25,6 +25,8 @@ static const chunk_t MS_AVP_Success = chunk_from_chars( 0x80, 0x03, 0x00, 0x02, 0x00, 0x01); static const chunk_t MS_AVP_Failure = chunk_from_chars( 0x80, 0x03, 0x00, 0x02, 0x00, 0x02); +static const chunk_t MS_SoH_Request = chunk_from_chars( + 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00); typedef struct private_eap_peap_avp_t private_eap_peap_avp_t; @@ -45,7 +47,7 @@ struct private_eap_peap_avp_t { }; METHOD(eap_peap_avp_t, build, void, - private_eap_peap_avp_t *this, tls_writer_t *writer, chunk_t data) + private_eap_peap_avp_t *this, bio_writer_t *writer, chunk_t data) { u_int8_t code; eap_packet_t *pkt; @@ -62,6 +64,19 @@ METHOD(eap_peap_avp_t, build, void, writer->write_uint8(writer, EAP_MSTLV); avp_data = (pkt->code == EAP_SUCCESS) ? MS_AVP_Success : MS_AVP_Failure; } + /** + * Still trying to form a correct MS SoH Request + * + else if (pkt->type == EAP_MSCHAPV2) + { + code = (this->is_server) ? EAP_REQUEST : EAP_RESPONSE; + writer->write_uint8(writer, code); + writer->write_uint8(writer, pkt->identifier); + writer->write_uint16(writer, 16); + writer->write_uint8(writer, EAP_EXPANDED); + avp_data = MS_SoH_Request; + } + */ else { avp_data = chunk_skip(data, 4); @@ -70,7 +85,7 @@ METHOD(eap_peap_avp_t, build, void, } METHOD(eap_peap_avp_t, process, status_t, - private_eap_peap_avp_t* this, tls_reader_t *reader, chunk_t *data, + private_eap_peap_avp_t* this, bio_reader_t *reader, chunk_t *data, u_int8_t identifier) { u_int8_t code; diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.h b/src/libcharon/plugins/eap_peap/eap_peap_avp.h index db22f0f8f..98c5f1912 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_avp.h +++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.h @@ -25,8 +25,8 @@ typedef struct eap_peap_avp_t eap_peap_avp_t; #include <library.h> -#include <tls_reader.h> -#include <tls_writer.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> /** * EAP-PEAP Attribute-Value Pair (AVP) handler. @@ -44,7 +44,7 @@ struct eap_peap_avp_t { * - FAILED if AVP processing failed * - NEED_MORE if another invocation of process/build needed */ - status_t (*process)(eap_peap_avp_t *this, tls_reader_t *reader, + status_t (*process)(eap_peap_avp_t *this, bio_reader_t *reader, chunk_t *data, u_int8_t identifier); /** @@ -53,7 +53,7 @@ struct eap_peap_avp_t { * @param writer TLS data buffer to write to * @param data EAP Message to send */ - void (*build)(eap_peap_avp_t *this, tls_writer_t *writer, chunk_t data); + void (*build)(eap_peap_avp_t *this, bio_writer_t *writer, chunk_t data); /** * Destroy a eap_peap_application_t. diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c index ca2af4fee..72e201fb6 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_peer.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c @@ -63,7 +63,7 @@ struct private_eap_peap_peer_t { }; METHOD(tls_application_t, process, status_t, - private_eap_peap_peer_t *this, tls_reader_t *reader) + private_eap_peap_peer_t *this, bio_reader_t *reader) { chunk_t data = chunk_empty; status_t status; @@ -185,7 +185,7 @@ METHOD(tls_application_t, process, status_t, } METHOD(tls_application_t, build, status_t, - private_eap_peap_peer_t *this, tls_writer_t *writer) + private_eap_peap_peer_t *this, bio_writer_t *writer) { chunk_t data; eap_code_t code; diff --git a/src/libcharon/plugins/eap_peap/eap_peap_plugin.c b/src/libcharon/plugins/eap_peap/eap_peap_plugin.c index bac5f2d3e..e8deee9e1 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_plugin.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_plugin.c @@ -25,13 +25,31 @@ METHOD(plugin_t, get_name, char*, return "eap-peap"; } +METHOD(plugin_t, get_features, int, + eap_peap_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_peap_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_PEAP), + PLUGIN_DEPENDS(EAP_SERVER, EAP_IDENTITY), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(eap_method_register, eap_peap_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_PEAP), + PLUGIN_DEPENDS(EAP_PEER, EAP_IDENTITY), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(RNG, RNG_STRONG), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_peap_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_peap_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_peap_create_peer); free(this); } @@ -45,15 +63,10 @@ plugin_t *eap_peap_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_PEAP, 0, EAP_SERVER, - (eap_constructor_t)eap_peap_create_server); - charon->eap->add_method(charon->eap, EAP_PEAP, 0, EAP_PEER, - (eap_constructor_t)eap_peap_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c index 3fabc3575..4acdd9f07 100644 --- a/src/libcharon/plugins/eap_peap/eap_peap_server.c +++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c @@ -158,7 +158,7 @@ static status_t start_phase2_tnc(private_eap_peap_server_t *this) } METHOD(tls_application_t, process, status_t, - private_eap_peap_server_t *this, tls_reader_t *reader) + private_eap_peap_server_t *this, bio_reader_t *reader) { chunk_t data = chunk_empty; status_t status; @@ -330,7 +330,7 @@ METHOD(tls_application_t, process, status_t, } METHOD(tls_application_t, build, status_t, - private_eap_peap_server_t *this, tls_writer_t *writer) + private_eap_peap_server_t *this, bio_writer_t *writer) { chunk_t data; eap_code_t code; diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index afc50bced..181497ab5 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -1,21 +1,21 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius AM_CFLAGS = -rdynamic if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-radius.la else +libstrongswan_eap_radius_la_LIBADD = $(top_builddir)/src/libradius/libradius.la plugin_LTLIBRARIES = libstrongswan-eap-radius.la endif libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ - radius_server.h radius_server.c \ - radius_socket.h radius_socket.c \ - radius_client.h radius_client.c \ - radius_message.h radius_message.c + eap_radius_accounting.h eap_radius_accounting.c \ + eap_radius_dae.h eap_radius_dae.c \ + eap_radius_forward.h eap_radius_forward.c libstrongswan_eap_radius_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 740c64055..0bef44042 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -74,10 +74,11 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_radius_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_eap_radius_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libradius/libradius.la am_libstrongswan_eap_radius_la_OBJECTS = eap_radius_plugin.lo \ - eap_radius.lo radius_server.lo radius_socket.lo \ - radius_client.lo radius_message.lo + eap_radius.lo eap_radius_accounting.lo eap_radius_dae.lo \ + eap_radius_forward.lo libstrongswan_eap_radius_la_OBJECTS = \ $(am_libstrongswan_eap_radius_la_OBJECTS) libstrongswan_eap_radius_la_LINK = $(LIBTOOL) --tag=CC \ @@ -196,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -279,18 +287,18 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-radius.la +@MONOLITHIC_FALSE@libstrongswan_eap_radius_la_LIBADD = $(top_builddir)/src/libradius/libradius.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-radius.la libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ - radius_server.h radius_server.c \ - radius_socket.h radius_socket.c \ - radius_client.h radius_client.c \ - radius_message.h radius_message.c + eap_radius_accounting.h eap_radius_accounting.c \ + eap_radius_dae.h eap_radius_dae.c \ + eap_radius_forward.h eap_radius_forward.c libstrongswan_eap_radius_la_LDFLAGS = -module -avoid-version all: all-am @@ -377,11 +385,10 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_accounting.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_dae.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_forward.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_plugin.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_client.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_message.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_server.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_socket.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index dfe0e2e09..c0a3703b6 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -14,14 +14,14 @@ */ #include "eap_radius.h" +#include "eap_radius_plugin.h" +#include "eap_radius_forward.h" -#include "radius_message.h" -#include "radius_client.h" +#include <radius_message.h> +#include <radius_client.h> #include <daemon.h> -#define TUNNEL_TYPE_ESP 9 - typedef struct private_eap_radius_t private_eap_radius_t; /** @@ -162,7 +162,7 @@ METHOD(eap_method_t, initiate, status_t, status_t status = FAILED; chunk_t username; - request = radius_message_create_request(); + request = radius_message_create(RMC_ACCESS_REQUEST); username = chunk_create(this->id_prefix, strlen(this->id_prefix)); username = chunk_cata("cc", username, this->peer->get_encoding(this->peer)); request->add(request, RAT_USER_NAME, username); @@ -175,16 +175,22 @@ METHOD(eap_method_t, initiate, status_t, { add_eap_identity(this, request); } + eap_radius_forward_from_ike(request); response = this->client->request(this->client, request); if (response) { + eap_radius_forward_to_ike(response); if (radius2ike(this, response, out)) { status = NEED_MORE; } response->destroy(response); } + else + { + charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING); + } request->destroy(request); return status; } @@ -253,7 +259,7 @@ static void process_filter_id(private_eap_radius_t *this, radius_message_t *msg) tunnel_type = untoh32(data.ptr); DBG1(DBG_IKE, "received RADIUS attribute Tunnel-Type: " "tag = %u, value = %u", tunnel_tag, tunnel_type); - is_esp_tunnel = (tunnel_type == TUNNEL_TYPE_ESP); + is_esp_tunnel = (tunnel_type == RADIUS_TUNNEL_TYPE_ESP); break; case RAT_FILTER_ID: filter_id = data; @@ -282,6 +288,31 @@ static void process_filter_id(private_eap_radius_t *this, radius_message_t *msg) } } +/** + * Handle Session-Timeout attribte + */ +static void process_timeout(private_eap_radius_t *this, radius_message_t *msg) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + chunk_t data; + int type; + + enumerator = msg->create_enumerator(msg); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == RAT_SESSION_TIMEOUT && data.len == 4) + { + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa) + { + ike_sa->set_auth_lifetime(ike_sa, untoh32(data.ptr)); + } + } + } + enumerator->destroy(enumerator); +} + METHOD(eap_method_t, process, status_t, private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out) { @@ -289,22 +320,25 @@ METHOD(eap_method_t, process, status_t, status_t status = FAILED; chunk_t data; - request = radius_message_create_request(); + request = radius_message_create(RMC_ACCESS_REQUEST); request->add(request, RAT_USER_NAME, this->peer->get_encoding(this->peer)); data = in->get_data(in); DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &data); - - /* fragment data suitable for RADIUS (not more than 253 bytes) */ - while (data.len > 253) + + /* fragment data suitable for RADIUS */ + while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE) { - request->add(request, RAT_EAP_MESSAGE, chunk_create(data.ptr, 253)); - data = chunk_skip(data, 253); + request->add(request, RAT_EAP_MESSAGE, + chunk_create(data.ptr,MAX_RADIUS_ATTRIBUTE_SIZE)); + data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE); } request->add(request, RAT_EAP_MESSAGE, data); + eap_radius_forward_from_ike(request); response = this->client->request(this->client, request); if (response) { + eap_radius_forward_to_ike(response); switch (response->get_code(response)) { case RMC_ACCESS_CHALLENGE: @@ -324,6 +358,7 @@ METHOD(eap_method_t, process, status_t, { process_filter_id(this, response); } + process_timeout(this, response); DBG1(DBG_IKE, "RADIUS authentication of '%Y' successful", this->peer); status = SUCCESS; @@ -427,7 +462,7 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer "charon.plugins.eap-radius.filter_id", FALSE), ); - this->client = radius_client_create(); + this->client = eap_radius_create_client(); if (!this->client) { free(this); diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c new file mode 100644 index 000000000..45be22704 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "eap_radius_accounting.h" +#include "eap_radius_plugin.h" + +#include <time.h> + +#include <radius_message.h> +#include <radius_client.h> +#include <daemon.h> +#include <utils/hashtable.h> +#include <threading/mutex.h> + +typedef struct private_eap_radius_accounting_t private_eap_radius_accounting_t; + +/** + * Private data of an eap_radius_accounting_t object. + */ +struct private_eap_radius_accounting_t { + + /** + * Public eap_radius_accounting_t interface. + */ + eap_radius_accounting_t public; + + /** + * Hashtable with sessions, IKE_SA unique id => entry_t + */ + hashtable_t *sessions; + + /** + * Mutex to lock sessions + */ + mutex_t *mutex; + + /** + * Session ID prefix + */ + u_int32_t prefix; +}; + +/** + * Hashtable entry with usage stats + */ +typedef struct { + /** RADIUS accounting session ID */ + char sid[16]; + /** number of octets sent */ + u_int64_t sent; + /** number of octets received */ + u_int64_t received; + /** session creation time */ + time_t created; +} entry_t; + +/** + * Accounting message status types + */ +typedef enum { + ACCT_STATUS_START = 1, + ACCT_STATUS_STOP = 2, + ACCT_STATUS_INTERIM_UPDATE = 3, + ACCT_STATUS_ACCOUNTING_ON = 7, + ACCT_STATUS_ACCOUNTING_OFF = 8, +} radius_acct_status_t; + +/** + * Hashtable hash function + */ +static u_int hash(uintptr_t key) +{ + return key; +} + +/** + * Hashtable equals function + */ +static bool equals(uintptr_t a, uintptr_t b) +{ + return a == b; +} + +/** + * Update usage counter when a CHILD_SA rekeys/goes down + */ +static void update_usage(private_eap_radius_accounting_t *this, + ike_sa_t *ike_sa, child_sa_t *child_sa) +{ + u_int64_t sent, received; + entry_t *entry; + + child_sa->get_usestats(child_sa, FALSE, NULL, &sent); + child_sa->get_usestats(child_sa, TRUE, NULL, &received); + + this->mutex->lock(this->mutex); + entry = this->sessions->get(this->sessions, + (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa)); + if (entry) + { + entry->sent += sent; + entry->received += received; + } + this->mutex->unlock(this->mutex); +} + +/** + * Send a RADIUS message, wait for response + */ +static bool send_message(private_eap_radius_accounting_t *this, + radius_message_t *request) +{ + radius_message_t *response; + radius_client_t *client; + bool ack = FALSE; + + client = eap_radius_create_client(); + if (client) + { + response = client->request(client, request); + if (response) + { + ack = response->get_code(response) == RMC_ACCOUNTING_RESPONSE; + response->destroy(response); + } + else + { + charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING); + } + client->destroy(client); + } + return ack; +} + +/** + * Add common IKE_SA parameters to RADIUS account message + */ +static void add_ike_sa_parameters(radius_message_t *message, ike_sa_t *ike_sa) +{ + host_t *vip; + char buf[64]; + chunk_t data; + + snprintf(buf, sizeof(buf), "%Y", ike_sa->get_other_eap_id(ike_sa)); + message->add(message, RAT_USER_NAME, chunk_create(buf, strlen(buf))); + snprintf(buf, sizeof(buf), "%#H", ike_sa->get_other_host(ike_sa)); + message->add(message, RAT_CALLING_STATION_ID, chunk_create(buf, strlen(buf))); + vip = ike_sa->get_virtual_ip(ike_sa, FALSE); + if (vip && vip->get_family(vip) == AF_INET) + { + message->add(message, RAT_FRAMED_IP_ADDRESS, vip->get_address(vip)); + } + if (vip && vip->get_family(vip) == AF_INET6) + { + /* we currently assign /128 prefixes, only (reserved, length) */ + data = chunk_from_chars(0, 128); + data = chunk_cata("cc", data, vip->get_address(vip)); + message->add(message, RAT_FRAMED_IPV6_PREFIX, data); + } +} + +/** + * Send an accounting start message + */ +static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa) +{ + radius_message_t *message; + entry_t *entry; + u_int32_t id, value; + + id = ike_sa->get_unique_id(ike_sa); + INIT(entry, + .created = time_monotonic(NULL), + ); + snprintf(entry->sid, sizeof(entry->sid), "%u-%u", this->prefix, id); + + message = radius_message_create(RMC_ACCOUNTING_REQUEST); + value = htonl(ACCT_STATUS_START); + message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value)); + message->add(message, RAT_ACCT_SESSION_ID, + chunk_create(entry->sid, strlen(entry->sid))); + add_ike_sa_parameters(message, ike_sa); + if (send_message(this, message)) + { + this->mutex->lock(this->mutex); + entry = this->sessions->put(this->sessions, (void*)(uintptr_t)id, entry); + this->mutex->unlock(this->mutex); + free(entry); + } + message->destroy(message); +} + +/** + * Send an account stop message + */ +static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa) +{ + radius_message_t *message; + entry_t *entry; + u_int32_t id, value; + + id = ike_sa->get_unique_id(ike_sa); + this->mutex->lock(this->mutex); + entry = this->sessions->remove(this->sessions, (void*)(uintptr_t)id); + this->mutex->unlock(this->mutex); + if (entry) + { + message = radius_message_create(RMC_ACCOUNTING_REQUEST); + value = htonl(ACCT_STATUS_STOP); + message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value)); + message->add(message, RAT_ACCT_SESSION_ID, + chunk_create(entry->sid, strlen(entry->sid))); + add_ike_sa_parameters(message, ike_sa); + value = htonl(entry->sent); + message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value)); + value = htonl(entry->sent >> 32); + if (value) + { + message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS, + chunk_from_thing(value)); + } + value = htonl(entry->received); + message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value)); + value = htonl(entry->received >> 32); + if (value) + { + message->add(message, RAT_ACCT_INPUT_GIGAWORDS, + chunk_from_thing(value)); + } + value = htonl(time_monotonic(NULL) - entry->created); + message->add(message, RAT_ACCT_SESSION_TIME, chunk_from_thing(value)); + + send_message(this, message); + message->destroy(message); + free(entry); + } +} + +METHOD(listener_t, ike_updown, bool, + private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, bool up) +{ + if (!up) + { + enumerator_t *enumerator; + child_sa_t *child_sa; + + /* update usage for all children just before sending stop */ + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, &child_sa)) + { + update_usage(this, ike_sa, child_sa); + } + enumerator->destroy(enumerator); + + send_stop(this, ike_sa); + } + return TRUE; +} + +METHOD(listener_t, message_hook, bool, + private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, + message_t *message, bool incoming) +{ + /* start accounting here, virtual IP now is set */ + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + message->get_exchange_type(message) == IKE_AUTH && + !incoming && !message->get_request(message)) + { + send_start(this, ike_sa); + } + return TRUE; +} + +METHOD(listener_t, child_rekey, bool, + private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, + child_sa_t *old, child_sa_t *new) +{ + update_usage(this, ike_sa, old); + + return TRUE; +} + +METHOD(listener_t, child_updown, bool, + private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, + child_sa_t *child_sa, bool up) +{ + if (!up && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED) + { + update_usage(this, ike_sa, child_sa); + } + return TRUE; +} + +METHOD(eap_radius_accounting_t, destroy, void, + private_eap_radius_accounting_t *this) +{ + this->mutex->destroy(this->mutex); + this->sessions->destroy(this->sessions); + free(this); +} + +/** + * See header + */ +eap_radius_accounting_t *eap_radius_accounting_create() +{ + private_eap_radius_accounting_t *this; + + INIT(this, + .public = { + .listener = { + .ike_updown = _ike_updown, + .message = _message_hook, + .child_updown = _child_updown, + .child_rekey = _child_rekey, + }, + .destroy = _destroy, + }, + /* use system time as Session ID prefix */ + .prefix = (u_int32_t)time(NULL), + .sessions = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 32), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.h b/src/libcharon/plugins/eap_radius/eap_radius_accounting.h new file mode 100644 index 000000000..811a5bb90 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 eap_radius_accounting eap_radius_accounting + * @{ @ingroup eap_radius + */ + +#ifndef EAP_RADIUS_ACCOUNTING_H_ +#define EAP_RADIUS_ACCOUNTING_H_ + +#include <bus/listeners/listener.h> + +typedef struct eap_radius_accounting_t eap_radius_accounting_t; + +/** + * RADIUS accounting for IKE/IPsec. + */ +struct eap_radius_accounting_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a eap_radius_accounting_t. + */ + void (*destroy)(eap_radius_accounting_t *this); +}; + +/** + * Create a eap_radius_accounting instance. + */ +eap_radius_accounting_t *eap_radius_accounting_create(); + +#endif /** EAP_RADIUS_ACCOUNTING_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c new file mode 100644 index 000000000..e84fe5b9c --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "eap_radius_dae.h" + +#include <radius_message.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <unistd.h> +#include <errno.h> + +#include <daemon.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> +#include <processing/jobs/delete_ike_sa_job.h> + +#define RADIUS_DAE_PORT 3799 + +typedef struct private_eap_radius_dae_t private_eap_radius_dae_t; + +/** + * Private data of an eap_radius_dae_t object. + */ +struct private_eap_radius_dae_t { + + /** + * Public eap_radius_dae_t interface. + */ + eap_radius_dae_t public; + + /** + * RADIUS session state + */ + eap_radius_accounting_t *accounting; + + /** + * Socket to listen on authorization extension port + */ + int fd; + + /** + * Listen job + */ + callback_job_t *job; + + /** + * RADIUS shared secret for DAE exchanges + */ + chunk_t secret; + + /** + * MD5 hasher + */ + hasher_t *hasher; + + /** + * HMAC MD5 signer, with secret set + */ + signer_t *signer; + + /** + * List of responses for retransmission, as entry_t + */ + linked_list_t *responses; +}; + +/** + * Entry to store responses for retransmit + */ +typedef struct { + /** stored response */ + radius_message_t *response; + /** client that sent the request */ + host_t *client; +} entry_t; + +/** + * Clean up an entry + */ +static void entry_destroy(entry_t *entry) +{ + entry->response->destroy(entry->response); + entry->client->destroy(entry->client); + free(entry); +} + +/** + * Save/Replace response for retransmission + */ +static void save_retransmit(private_eap_radius_dae_t *this, + radius_message_t *response, host_t *client) +{ + enumerator_t *enumerator; + entry_t *entry; + bool found = FALSE; + + enumerator = this->responses->create_enumerator(this->responses); + while (enumerator->enumerate(enumerator, &entry)) + { + if (client->equals(client, entry->client)) + { + entry->response->destroy(entry->response); + entry->response = response; + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + INIT(entry, + .response = response, + .client = client->clone(client), + ); + this->responses->insert_first(this->responses, entry); + } +} + +/** + * Send a RADIUS message to client + */ +static void send_message(private_eap_radius_dae_t *this, + radius_message_t *message, host_t *client) +{ + chunk_t data; + + data = message->get_encoding(message); + if (sendto(this->fd, data.ptr, data.len, 0, client->get_sockaddr(client), + *client->get_sockaddr_len(client)) != data.len) + { + DBG1(DBG_CFG, "sending RADIUS DAE response failed: %s", strerror(errno)); + } +} + +/** + * Check if we request is a retransmit, retransmit stored response + */ +static bool send_retransmit(private_eap_radius_dae_t *this, + radius_message_t *request, host_t *client) +{ + enumerator_t *enumerator; + entry_t *entry; + bool found = FALSE; + + enumerator = this->responses->create_enumerator(this->responses); + while (enumerator->enumerate(enumerator, &entry)) + { + if (client->equals(client, entry->client) && + request->get_identifier(request) == + entry->response->get_identifier(entry->response)) + { + DBG1(DBG_CFG, "received retransmit of RADIUS %N, retransmitting %N " + "to %H", radius_message_code_names, request->get_code(request), + radius_message_code_names, + entry->response->get_code(entry->response), client); + send_message(this, entry->response, client); + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + +/** + * Send an ACK/NAK response for a request + */ +static void send_response(private_eap_radius_dae_t *this, + radius_message_t *request, radius_message_code_t code, + host_t *client) +{ + radius_message_t *response; + + response = radius_message_create(code); + response->set_identifier(response, request->get_identifier(request)); + response->sign(response, request->get_authenticator(request), + this->secret, this->hasher, this->signer, NULL, FALSE); + + send_message(this, response, client); + save_retransmit(this, response, client); +} + +/** + * Add all IKE_SAs matching to user to a list + */ +static void add_matching_ike_sas(linked_list_t *list, identification_t *user) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + ike_sa_id_t *id; + + enumerator = charon->ike_sa_manager->create_enumerator( + charon->ike_sa_manager, FALSE); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (user->matches(user, ike_sa->get_other_eap_id(ike_sa))) + { + id = ike_sa->get_id(ike_sa); + list->insert_last(list, id->clone(id)); + } + } + enumerator->destroy(enumerator); +} + +/** + * Get list of IKE_SAs matching a Disconnect/CoA request + */ +static linked_list_t *get_matching_ike_sas(private_eap_radius_dae_t *this, + radius_message_t *request, host_t *client) +{ + enumerator_t *enumerator; + identification_t *user; + linked_list_t *ids; + chunk_t data; + int type; + + ids = linked_list_create(); + + enumerator = request->create_enumerator(request); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == RAT_USER_NAME && data.len) + { + user = identification_create_from_data(data); + DBG1(DBG_CFG, "received RADIUS DAE %N for %Y from %H", + radius_message_code_names, request->get_code(request), + user, client); + add_matching_ike_sas(ids, user); + user->destroy(user); + } + } + enumerator->destroy(enumerator); + + return ids; +} + +/** + * Process a DAE disconnect request, send response + */ +static void process_disconnect(private_eap_radius_dae_t *this, + radius_message_t *request, host_t *client) +{ + enumerator_t *enumerator; + linked_list_t *ids; + ike_sa_id_t *id; + + ids = get_matching_ike_sas(this, request, client); + + if (ids->get_count(ids)) + { + DBG1(DBG_CFG, "closing %d IKE_SA%s matching %N, sending %N", + ids->get_count(ids), ids->get_count(ids) > 1 ? "s" : "", + radius_message_code_names, RMC_DISCONNECT_REQUEST, + radius_message_code_names, RMC_DISCONNECT_ACK); + + enumerator = ids->create_enumerator(ids); + while (enumerator->enumerate(enumerator, &id)) + { + lib->processor->queue_job(lib->processor, (job_t*) + delete_ike_sa_job_create(id, TRUE)); + } + enumerator->destroy(enumerator); + + send_response(this, request, RMC_DISCONNECT_ACK, client); + } + else + { + DBG1(DBG_CFG, "no IKE_SA matches %N, sending %N", + radius_message_code_names, RMC_DISCONNECT_REQUEST, + radius_message_code_names, RMC_DISCONNECT_NAK); + send_response(this, request, RMC_DISCONNECT_NAK, client); + } + ids->destroy_offset(ids, offsetof(ike_sa_id_t, destroy)); +} + +/** + * Apply a new lifetime to an IKE_SA + */ +static void apply_lifetime(private_eap_radius_dae_t *this, ike_sa_id_t *id, + u_int32_t lifetime) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + if (ike_sa) + { + if (ike_sa->set_auth_lifetime(ike_sa, lifetime) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } +} + +/** + * Process a DAE CoA request, send response + */ +static void process_coa(private_eap_radius_dae_t *this, + radius_message_t *request, host_t *client) +{ + enumerator_t *enumerator; + linked_list_t *ids; + ike_sa_id_t *id; + chunk_t data; + int type; + u_int32_t lifetime = 0; + bool lifetime_seen = FALSE; + + ids = get_matching_ike_sas(this, request, client); + + if (ids->get_count(ids)) + { + enumerator = request->create_enumerator(request); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == RAT_SESSION_TIMEOUT && data.len == 4) + { + lifetime = untoh32(data.ptr); + lifetime_seen = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (lifetime_seen) + { + DBG1(DBG_CFG, "applying %us lifetime to %d IKE_SA%s matching %N, " + "sending %N", lifetime, ids->get_count(ids), + ids->get_count(ids) > 1 ? "s" : "", + radius_message_code_names, RMC_COA_REQUEST, + radius_message_code_names, RMC_COA_ACK); + + enumerator = ids->create_enumerator(ids); + while (enumerator->enumerate(enumerator, &id)) + { + apply_lifetime(this, id, lifetime); + } + enumerator->destroy(enumerator); + send_response(this, request, RMC_COA_ACK, client); + } + else + { + DBG1(DBG_CFG, "no Session-Timeout attribute found in %N, sending %N", + radius_message_code_names, RMC_COA_REQUEST, + radius_message_code_names, RMC_COA_NAK); + send_response(this, request, RMC_COA_NAK, client); + } + } + else + { + DBG1(DBG_CFG, "no IKE_SA matches %N, sending %N", + radius_message_code_names, RMC_COA_REQUEST, + radius_message_code_names, RMC_COA_NAK); + send_response(this, request, RMC_COA_NAK, client); + } + ids->destroy_offset(ids, offsetof(ike_sa_id_t, destroy)); +} + +/** + * Receive RADIUS DAE requests + */ +static job_requeue_t receive(private_eap_radius_dae_t *this) +{ + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + radius_message_t *request; + char buf[2048]; + ssize_t len; + bool oldstate; + host_t *client; + + oldstate = thread_cancelability(TRUE); + len = recvfrom(this->fd, buf, sizeof(buf), 0, + (struct sockaddr*)&addr, &addr_len); + thread_cancelability(oldstate); + + if (len > 0) + { + request = radius_message_parse(chunk_create(buf, len)); + if (request) + { + client = host_create_from_sockaddr((struct sockaddr*)&addr); + if (client) + { + if (!send_retransmit(this, request, client)) + { + if (request->verify(request, NULL, this->secret, + this->hasher, this->signer)) + { + switch (request->get_code(request)) + { + case RMC_DISCONNECT_REQUEST: + process_disconnect(this, request, client); + break; + case RMC_COA_REQUEST: + process_coa(this, request, client); + break; + default: + DBG1(DBG_CFG, "ignoring unsupported RADIUS DAE " + "%N message from %H", + radius_message_code_names, + request->get_code(request), client); + break; + } + } + } + client->destroy(client); + } + request->destroy(request); + } + else + { + DBG1(DBG_NET, "ignoring invalid RADIUS DAE request"); + } + } + else + { + DBG1(DBG_NET, "receiving RADIUS DAE request failed: %s", strerror(errno)); + } + return JOB_REQUEUE_DIRECT; +} + +/** + * Open DAE socket + */ +static bool open_socket(private_eap_radius_dae_t *this) +{ + host_t *host; + + this->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (this->fd == -1) + { + DBG1(DBG_CFG, "unable to open RADIUS DAE socket: %s", strerror(errno)); + return FALSE; + } + + host = host_create_from_string( + lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.dae.listen", "0.0.0.0"), + lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.dae.port", RADIUS_DAE_PORT)); + if (!host) + { + DBG1(DBG_CFG, "invalid RADIUS DAE listen address"); + return FALSE; + } + + if (bind(this->fd, host->get_sockaddr(host), + *host->get_sockaddr_len(host)) == -1) + { + DBG1(DBG_CFG, "unable to bind RADIUS DAE socket: %s", strerror(errno)); + host->destroy(host); + return FALSE; + } + host->destroy(host); + return TRUE; +} + +METHOD(eap_radius_dae_t, destroy, void, + private_eap_radius_dae_t *this) +{ + if (this->job) + { + this->job->cancel(this->job); + } + if (this->fd != -1) + { + close(this->fd); + } + DESTROY_IF(this->signer); + DESTROY_IF(this->hasher); + this->responses->destroy_function(this->responses, (void*)entry_destroy); + free(this); +} + +/** + * See header + */ +eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting) +{ + private_eap_radius_dae_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .accounting = accounting, + .fd = -1, + .secret = { + .ptr = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.dae.secret", NULL), + }, + .hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5), + .signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128), + .responses = linked_list_create(), + ); + + if (!this->hasher || !this->signer) + { + destroy(this); + return NULL; + } + if (!this->secret.ptr) + { + DBG1(DBG_CFG, "missing RADIUS DAE secret, disabled"); + destroy(this); + return NULL; + } + this->secret.len = strlen(this->secret.ptr); + this->signer->set_key(this->signer, this->secret); + + if (!open_socket(this)) + { + destroy(this); + return NULL; + } + + 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; +} diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.h b/src/libcharon/plugins/eap_radius/eap_radius_dae.h new file mode 100644 index 000000000..759eadb49 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 eap_radius_dae eap_radius_dae + * @{ @ingroup eap_radius + */ + +#ifndef EAP_RADIUS_DAE_H_ +#define EAP_RADIUS_DAE_H_ + +#include "eap_radius_accounting.h" + +typedef struct eap_radius_dae_t eap_radius_dae_t; + +/** + * Dynamic Authorization Extensions (RFC 5176) for EAP-RADIUS. + */ +struct eap_radius_dae_t { + + /** + * Destroy a eap_radius_dae_t. + */ + void (*destroy)(eap_radius_dae_t *this); +}; + +/** + * Create a eap_radius_dae instance. + */ +eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting); + +#endif /** EAP_RADIUS_DAE_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.c b/src/libcharon/plugins/eap_radius/eap_radius_forward.c new file mode 100644 index 000000000..cb4ca74e3 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.c @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "eap_radius_forward.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <utils/hashtable.h> +#include <threading/mutex.h> + +typedef struct private_eap_radius_forward_t private_eap_radius_forward_t; + +/** + * Private data of an eap_radius_forward_t object. + */ +struct private_eap_radius_forward_t { + + /** + * Public eap_radius_forward_t interface. + */ + eap_radius_forward_t public; + + /** + * List of attribute types to copy from IKE, as attr_t + */ + linked_list_t *from_attr; + + /** + * List of attribute types to copy to IKE, as attr_t + */ + linked_list_t *to_attr; + + /** + * Queued to forward from IKE, unique_id => linked_list_t of chunk_t + */ + hashtable_t *from; + + /** + * Queued to forward to IKE, unique_id => linked_list_t of chunk_t + */ + hashtable_t *to; + + /** + * Mutex to lock concurrent access to hashtables + */ + mutex_t *mutex; +}; + +/** + * RADIUS attribute selector + */ +typedef struct { + /** vendor ID, 0 for standard attributes */ + u_int32_t vendor; + /** attribute type */ + u_int8_t type; +} attr_t; + +/** + * Single instance of this + */ +static private_eap_radius_forward_t *singleton = NULL; + +/** + * Hashtable hash function + */ +static u_int hash(uintptr_t key) +{ + return key; +} + +/** + * Hashtable equals function + */ +static bool equals(uintptr_t a, uintptr_t b) +{ + return a == b; +} + +/** + * Free a queue entry + */ +static void free_attribute(chunk_t *chunk) +{ + free(chunk->ptr); + free(chunk); +} + +/** + * Lookup/create an attribute queue from a table + */ +static linked_list_t *lookup_queue(private_eap_radius_forward_t *this, + hashtable_t *table) +{ + linked_list_t *queue = NULL; + ike_sa_t *ike_sa; + uintptr_t id; + + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN)) + { + id = ike_sa->get_unique_id(ike_sa); + this->mutex->lock(this->mutex); + queue = table->get(table, (void*)id); + if (!queue) + { + queue = linked_list_create(); + table->put(table, (void*)id, queue); + } + this->mutex->unlock(this->mutex); + } + return queue; +} + +/** + * Remove attribute queue from table + */ +static void remove_queue(private_eap_radius_forward_t *this, + hashtable_t *table, ike_sa_t *ike_sa) +{ + linked_list_t *queue; + + this->mutex->lock(this->mutex); + queue = table->remove(table, (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa)); + this->mutex->unlock(this->mutex); + if (queue) + { + queue->destroy_function(queue, (void*)free_attribute); + } +} + +/** + * Check if RADIUS attribute is contained in selector + */ +static bool is_attribute_selected(linked_list_t *selector, + radius_attribute_type_t type, chunk_t data) +{ + enumerator_t *enumerator; + u_int32_t vendor = 0; + attr_t *sel; + bool found = FALSE; + + if (type == RAT_VENDOR_SPECIFIC) + { + if (data.len < 4) + { + return FALSE; + } + vendor = untoh32(data.ptr); + } + enumerator = selector->create_enumerator(selector); + while (!found && enumerator->enumerate(enumerator, &sel)) + { + if (sel->vendor == vendor) + { + if (vendor) + { + if (sel->type == 0) + { /* any of that vendor is fine */ + found = TRUE; + } + else if (data.len > 4 && data.ptr[4] == sel->type) + { /* vendor specific type field, as defined in RFC 2865 */ + found = TRUE; + } + } + else + { + if (sel->type == type) + { + found = TRUE; + } + } + } + } + enumerator->destroy(enumerator); + + return found; +} + +/** + * Copy RADIUS attributes from queue to a RADIUS message + */ +static void queue2radius(linked_list_t *queue, radius_message_t *message) +{ + chunk_t *data; + + while (queue->remove_last(queue, (void**)&data) == SUCCESS) + { + if (data->len >= 2) + { + message->add(message, data->ptr[0], chunk_skip(*data, 2)); + } + free_attribute(data); + } +} + +/** + * Copy RADIUS attributes from a RADIUS message to the queue + */ +static void radius2queue(radius_message_t *message, linked_list_t *queue, + linked_list_t *selector) +{ + enumerator_t *enumerator; + int type; + chunk_t data, hdr, *ptr; + + enumerator = message->create_enumerator(message); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (is_attribute_selected(selector, type, data)) + { + hdr = chunk_alloc(2); + hdr.ptr[0] = type; + hdr.ptr[1] = data.len + 2; + + INIT(ptr); + *ptr = chunk_cat("mc", hdr, data); + queue->insert_last(queue, ptr); + } + } + enumerator->destroy(enumerator); +} + +/** + * Copy RADIUS attribute nofifies from IKE message to queue + */ +static void ike2queue(message_t *message, linked_list_t *queue, + linked_list_t *selector) +{ + enumerator_t *enumerator; + payload_t *payload; + notify_payload_t *notify; + chunk_t data, *ptr; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == NOTIFY) + { + notify = (notify_payload_t*)payload; + if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE) + { + data = notify->get_notification_data(notify); + if (data.len >= 2 && is_attribute_selected(selector, + data.ptr[0], chunk_skip(data, 2))) + { + INIT(ptr); + *ptr = chunk_clone(data); + queue->insert_last(queue, ptr); + } + } + } + } + enumerator->destroy(enumerator); +} + +/** + * Copy RADUIS attributes from queue to IKE message notifies + */ +static void queue2ike(linked_list_t *queue, message_t *message) +{ + chunk_t *data; + + while (queue->remove_last(queue, (void**)&data) == SUCCESS) + { + message->add_notify(message, FALSE, RADIUS_ATTRIBUTE, *data); + free_attribute(data); + } +} + +/** + * See header. + */ +void eap_radius_forward_from_ike(radius_message_t *request) +{ + private_eap_radius_forward_t *this = singleton; + linked_list_t *queue; + + if (this) + { + queue = lookup_queue(this, this->from); + if (queue) + { + queue2radius(queue, request); + } + } +} + +/** + * See header. + */ +void eap_radius_forward_to_ike(radius_message_t *response) +{ + private_eap_radius_forward_t *this = singleton; + linked_list_t *queue; + + if (this) + { + queue = lookup_queue(this, this->to); + if (queue) + { + radius2queue(response, queue, this->to_attr); + } + } +} + +METHOD(listener_t, message, bool, + private_eap_radius_forward_t *this, + ike_sa_t *ike_sa, message_t *message, bool incoming) +{ + linked_list_t *queue; + + if (message->get_exchange_type(message) == IKE_AUTH) + { + if (incoming) + { + queue = lookup_queue(this, this->from); + if (queue) + { + ike2queue(message, queue, this->from_attr); + } + } + else + { + queue = lookup_queue(this, this->to); + if (queue) + { + queue2ike(queue, message); + } + } + } + return TRUE; +} + +METHOD(listener_t, ike_updown, bool, + private_eap_radius_forward_t *this, ike_sa_t *ike_sa, bool up) +{ + /* up or down, we don't need the state anymore */ + remove_queue(this, this->from, ike_sa); + remove_queue(this, this->to, ike_sa); + return TRUE; +} + +/** + * Parse a selector string to a list of attr_t selectors + */ +static linked_list_t* parse_selector(char *selector) +{ + enumerator_t *enumerator; + linked_list_t *list; + char *token, *pos; + + list = linked_list_create(); + enumerator = enumerator_create_token(selector, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + int type, vendor = 0; + attr_t *attr; + + pos = strchr(token, ':'); + if (pos) + { + *(pos++) = 0; + vendor = atoi(token); + token = pos; + } + type = enum_from_name(radius_attribute_type_names, token); + if (type == -1) + { + type = atoi(token); + } + if (vendor == 0 && type == 0) + { + DBG1(DBG_CFG, "ignoring unknown RADIUS attribute type '%s'", token); + } + else + { + INIT(attr, + .type = type, + .vendor = vendor, + ); + list->insert_last(list, attr); + if (!vendor) + { + DBG1(DBG_IKE, "forwarding RADIUS attribute %N", + radius_attribute_type_names, type); + } + else + { + DBG1(DBG_IKE, "forwarding RADIUS VSA %d-%d", vendor, type); + } + } + } + enumerator->destroy(enumerator); + return list; +} + +METHOD(eap_radius_forward_t, destroy, void, + private_eap_radius_forward_t *this) +{ + this->from_attr->destroy_function(this->from_attr, free); + this->to_attr->destroy_function(this->to_attr, free); + this->from->destroy(this->from); + this->to->destroy(this->to); + this->mutex->destroy(this->mutex); + free(this); + singleton = NULL; +} + +/** + * See header + */ +eap_radius_forward_t *eap_radius_forward_create() +{ + private_eap_radius_forward_t *this; + + INIT(this, + .public = { + .listener = { + .message = _message, + .ike_updown = _ike_updown, + }, + .destroy = _destroy, + }, + .from_attr = parse_selector(lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.forward.ike_to_radius", "")), + .to_attr = parse_selector(lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.forward.radius_to_ike", "")), + .from = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 8), + .to = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 8), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + if (this->from_attr->get_count(this->from_attr) == 0 && + this->to_attr->get_count(this->to_attr) == 0) + { + destroy(this); + return NULL; + } + + singleton = this; + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.h b/src/libcharon/plugins/eap_radius/eap_radius_forward.h new file mode 100644 index 000000000..2c1dbf7a8 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 eap_radius_forward eap_radius_forward + * @{ @ingroup eap_radius + */ + +#ifndef EAP_RADIUS_FORWARD_H_ +#define EAP_RADIUS_FORWARD_H_ + +#include <radius_message.h> + +#include <bus/listeners/listener.h> + +typedef struct eap_radius_forward_t eap_radius_forward_t; + +/** + * Forward RADIUS attributes in Notifies between client and AAA backend. + */ +struct eap_radius_forward_t { + + /** + * Implements a listener. + */ + listener_t listener; + + /** + * Destroy a eap_radius_forward_t. + */ + void (*destroy)(eap_radius_forward_t *this); +}; + +/** + * Create a eap_radius_forward instance. + */ +eap_radius_forward_t *eap_radius_forward_create(); + +/** + * Forward RADIUS attributes from IKE notifies to a RADIUS request. + * + * @param request RADIUS request message to add attributes to + */ +void eap_radius_forward_from_ike(radius_message_t *request); + +/** + * Forward RADIUS attributes from a RADIUS response to IKE notifies. + * + * @param response RADIUS respose to read notifies from + */ +void eap_radius_forward_to_ike(radius_message_t *response); + +#endif /** EAP_RADIUS_FORWARD_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index c218bd48b..8ee0ab81a 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -16,16 +16,25 @@ #include "eap_radius_plugin.h" #include "eap_radius.h" -#include "radius_client.h" -#include "radius_server.h" +#include "eap_radius_accounting.h" +#include "eap_radius_dae.h" +#include "eap_radius_forward.h" + +#include <radius_client.h> +#include <radius_config.h> #include <daemon.h> #include <threading/rwlock.h> /** - * Default RADIUS server port, when not configured + * Default RADIUS server port for authentication */ -#define RADIUS_PORT 1812 +#define AUTH_PORT 1812 + +/** + * Default RADIUS server port for accounting + */ +#define ACCT_PORT 1813 typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t; @@ -40,14 +49,29 @@ struct private_eap_radius_plugin_t { eap_radius_plugin_t public; /** - * List of RADIUS servers + * List of RADIUS server configurations */ - linked_list_t *servers; + linked_list_t *configs; /** - * Lock for server list + * Lock for configs list */ rwlock_t *lock; + + /** + * RADIUS sessions for accounting + */ + eap_radius_accounting_t *accounting; + + /** + * Dynamic authorization extensions + */ + eap_radius_dae_t *dae; + + /** + * RADIUS <-> IKE attribute forwarding + */ + eap_radius_forward_t *forward; }; /** @@ -58,12 +82,12 @@ static private_eap_radius_plugin_t *instance = NULL; /** * Load RADIUS servers from configuration */ -static void load_servers(private_eap_radius_plugin_t *this) +static void load_configs(private_eap_radius_plugin_t *this) { enumerator_t *enumerator; - radius_server_t *server; + radius_config_t *config; char *nas_identifier, *secret, *address, *section; - int port, sockets, preference; + int auth_port, acct_port, sockets, preference; address = lib->settings->get_str(lib->settings, "charon.plugins.eap-radius.server", NULL); @@ -78,18 +102,18 @@ static void load_servers(private_eap_radius_plugin_t *this) } nas_identifier = lib->settings->get_str(lib->settings, "charon.plugins.eap-radius.nas_identifier", "strongSwan"); - port = lib->settings->get_int(lib->settings, - "charon.plugins.eap-radius.port", RADIUS_PORT); + auth_port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.port", AUTH_PORT); sockets = lib->settings->get_int(lib->settings, "charon.plugins.eap-radius.sockets", 1); - server = radius_server_create(address, address, port, nas_identifier, - secret, sockets, 0); - if (!server) + config = radius_config_create(address, address, auth_port, ACCT_PORT, + nas_identifier, secret, sockets, 0); + if (!config) { DBG1(DBG_CFG, "no RADUIS server defined"); return; } - this->servers->insert_last(this->servers, server); + this->configs->insert_last(this->configs, config); return; } @@ -114,26 +138,32 @@ static void load_servers(private_eap_radius_plugin_t *this) nas_identifier = lib->settings->get_str(lib->settings, "charon.plugins.eap-radius.servers.%s.nas_identifier", "strongSwan", section); - port = lib->settings->get_int(lib->settings, - "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section); + auth_port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.auth_port", + lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.port", + AUTH_PORT, section), + section); + acct_port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.acct_port", ACCT_PORT, section); sockets = lib->settings->get_int(lib->settings, "charon.plugins.eap-radius.servers.%s.sockets", 1, section); preference = lib->settings->get_int(lib->settings, "charon.plugins.eap-radius.servers.%s.preference", 0, section); - server = radius_server_create(section, address, port, nas_identifier, - secret, sockets, preference); - if (!server) + config = radius_config_create(section, address, auth_port, acct_port, + nas_identifier, secret, sockets, preference); + if (!config) { DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section); continue; } - this->servers->insert_last(this->servers, server); + this->configs->insert_last(this->configs, config); } enumerator->destroy(enumerator); DBG1(DBG_CFG, "loaded %d RADIUS server configuration%s", - this->servers->get_count(this->servers), - this->servers->get_count(this->servers) == 1 ? "" : "s"); + this->configs->get_count(this->configs), + this->configs->get_count(this->configs) == 1 ? "" : "s"); } METHOD(plugin_t, get_name, char*, @@ -142,14 +172,28 @@ METHOD(plugin_t, get_name, char*, return "eap-radius"; } +METHOD(plugin_t, get_features, int, + eap_radius_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_radius_create), + PLUGIN_PROVIDE(EAP_SERVER, EAP_RADIUS), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_MD5_128), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, reload, bool, private_eap_radius_plugin_t *this) { this->lock->write_lock(this->lock); - this->servers->destroy_offset(this->servers, - offsetof(radius_server_t, destroy)); - this->servers = linked_list_create(); - load_servers(this); + this->configs->destroy_offset(this->configs, + offsetof(radius_config_t, destroy)); + this->configs = linked_list_create(); + load_configs(this); this->lock->unlock(this->lock); return TRUE; } @@ -157,10 +201,17 @@ METHOD(plugin_t, reload, bool, METHOD(plugin_t, destroy, void, private_eap_radius_plugin_t *this) { - charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create); - this->servers->destroy_offset(this->servers, - offsetof(radius_server_t, destroy)); + if (this->forward) + { + charon->bus->remove_listener(charon->bus, &this->forward->listener); + this->forward->destroy(this->forward); + } + DESTROY_IF(this->dae); + this->configs->destroy_offset(this->configs, + offsetof(radius_config_t, destroy)); this->lock->destroy(this->lock); + charon->bus->remove_listener(charon->bus, &this->accounting->listener); + this->accounting->destroy(this->accounting); free(this); instance = NULL; } @@ -176,36 +227,78 @@ plugin_t *eap_radius_plugin_create() .public = { .plugin = { .get_name = _get_name, + .get_features = _get_features, .reload = _reload, .destroy = _destroy, }, }, - .servers = linked_list_create(), + .configs = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .accounting = eap_radius_accounting_create(), + .forward = eap_radius_forward_create(), ); - load_servers(this); - - charon->eap->add_method(charon->eap, EAP_RADIUS, 0, - EAP_SERVER, (eap_constructor_t)eap_radius_create); - + load_configs(this); instance = this; + if (lib->settings->get_bool(lib->settings, + "charon.plugins.eap-radius.accounting", FALSE)) + { + charon->bus->add_listener(charon->bus, &this->accounting->listener); + } + if (lib->settings->get_bool(lib->settings, + "charon.plugins.eap-radius.dae.enable", FALSE)) + { + this->dae = eap_radius_dae_create(this->accounting); + } + if (this->forward) + { + charon->bus->add_listener(charon->bus, &this->forward->listener); + } + return &this->public.plugin; } /** * See header */ -enumerator_t *eap_radius_create_server_enumerator() +radius_client_t *eap_radius_create_client() { if (instance) { + enumerator_t *enumerator; + radius_config_t *config, *selected = NULL; + int current, best = -1; + instance->lock->read_lock(instance->lock); - return enumerator_create_cleaner( - instance->servers->create_enumerator(instance->servers), - (void*)instance->lock->unlock, instance->lock); + enumerator = instance->configs->create_enumerator(instance->configs); + while (enumerator->enumerate(enumerator, &config)) + { + current = config->get_preference(config); + if (current > best || + /* for two with equal preference, 50-50 chance */ + (current == best && random() % 2 == 0)) + { + DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d", + config->get_name(config), current); + best = current; + DESTROY_IF(selected); + selected = config->get_ref(config); + } + else + { + DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d", + config->get_name(config), current); + } + } + enumerator->destroy(enumerator); + instance->lock->unlock(instance->lock); + + if (selected) + { + return radius_client_create(selected); + } } - return enumerator_create_empty(); + return NULL; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h index cb724364a..1570bd566 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h @@ -25,7 +25,8 @@ #define EAP_RADIUS_PLUGIN_H_ #include <plugins/plugin.h> -#include <utils/enumerator.h> + +#include <radius_client.h> typedef struct eap_radius_plugin_t eap_radius_plugin_t; @@ -44,10 +45,10 @@ struct eap_radius_plugin_t { }; /** - * Create an enumerator over all loaded RADIUS servers. + * Get a RADIUS client instance to connect to servers. * - * @return enumerator over radius_server_t + * @return RADIUS client */ -enumerator_t *eap_radius_create_server_enumerator(); +radius_client_t *eap_radius_create_client(); #endif /** EAP_RADIUS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c deleted file mode 100644 index 245308e59..000000000 --- a/src/libcharon/plugins/eap_radius/radius_client.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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 "radius_client.h" - -#include "eap_radius_plugin.h" -#include "radius_server.h" - -#include <unistd.h> -#include <errno.h> - -#include <daemon.h> -#include <utils/host.h> -#include <utils/linked_list.h> -#include <threading/condvar.h> -#include <threading/mutex.h> - -typedef struct private_radius_client_t private_radius_client_t; - -/** - * Private data of an radius_client_t object. - */ -struct private_radius_client_t { - - /** - * Public radius_client_t interface. - */ - radius_client_t public; - - /** - * Selected RADIUS server - */ - radius_server_t *server; - - /** - * RADIUS servers State attribute - */ - chunk_t state; - - /** - * EAP MSK, from MPPE keys - */ - chunk_t msk; -}; - -/** - * Save the state attribute to include in further request - */ -static void save_state(private_radius_client_t *this, radius_message_t *msg) -{ - enumerator_t *enumerator; - int type; - chunk_t data; - - enumerator = msg->create_enumerator(msg); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_STATE) - { - free(this->state.ptr); - this->state = chunk_clone(data); - enumerator->destroy(enumerator); - return; - } - } - enumerator->destroy(enumerator); - /* no state attribute found, remove state */ - chunk_free(&this->state); -} - -METHOD(radius_client_t, request, radius_message_t*, - private_radius_client_t *this, radius_message_t *req) -{ - char virtual[] = {0x00,0x00,0x00,0x05}; - radius_socket_t *socket; - radius_message_t *res; - - /* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */ - req->add(req, RAT_NAS_PORT_TYPE, chunk_create(virtual, sizeof(virtual))); - /* add our NAS-Identifier */ - req->add(req, RAT_NAS_IDENTIFIER, - this->server->get_nas_identifier(this->server)); - /* add State attribute, if server sent one */ - if (this->state.ptr) - { - req->add(req, RAT_STATE, this->state); - } - socket = this->server->get_socket(this->server); - DBG1(DBG_CFG, "sending RADIUS %N to server '%s'", radius_message_code_names, - req->get_code(req), this->server->get_name(this->server)); - res = socket->request(socket, req); - if (res) - { - DBG1(DBG_CFG, "received RADIUS %N from server '%s'", - radius_message_code_names, res->get_code(res), - this->server->get_name(this->server)); - save_state(this, res); - if (res->get_code(res) == RMC_ACCESS_ACCEPT) - { - chunk_clear(&this->msk); - this->msk = socket->decrypt_msk(socket, req, res); - } - this->server->put_socket(this->server, socket, TRUE); - return res; - } - this->server->put_socket(this->server, socket, FALSE); - charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING); - return NULL; -} - -METHOD(radius_client_t, get_msk, chunk_t, - private_radius_client_t *this) -{ - return this->msk; -} - -METHOD(radius_client_t, destroy, void, - private_radius_client_t *this) -{ - this->server->destroy(this->server); - chunk_clear(&this->msk); - free(this->state.ptr); - free(this); -} - -/** - * See header - */ -radius_client_t *radius_client_create() -{ - private_radius_client_t *this; - enumerator_t *enumerator; - radius_server_t *server; - int current, best = -1; - - INIT(this, - .public = { - .request = _request, - .get_msk = _get_msk, - .destroy = _destroy, - }, - ); - - enumerator = eap_radius_create_server_enumerator(); - while (enumerator->enumerate(enumerator, &server)) - { - current = server->get_preference(server); - if (current > best || - /* for two with equal preference, 50-50 chance */ - (current == best && random() % 2 == 0)) - { - DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d", - server->get_name(server), current); - best = current; - DESTROY_IF(this->server); - this->server = server->get_ref(server); - } - else - { - DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d", - server->get_name(server), current); - } - } - enumerator->destroy(enumerator); - - if (!this->server) - { - free(this); - return NULL; - } - - return &this->public; -} - diff --git a/src/libcharon/plugins/eap_radius/radius_client.h b/src/libcharon/plugins/eap_radius/radius_client.h deleted file mode 100644 index e4f3a7222..000000000 --- a/src/libcharon/plugins/eap_radius/radius_client.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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 radius_client radius_client - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_CLIENT_H_ -#define RADIUS_CLIENT_H_ - -#include "radius_message.h" - -typedef struct radius_client_t radius_client_t; - -/** - * RADIUS client functionality. - * - * To communicate with a RADIUS server, create a client and send messages over - * it. The client allocates a socket from the best RADIUS server abailable. - */ -struct radius_client_t { - - /** - * Send a RADIUS request and wait for the response. - * - * The client fills in NAS-Identifier nad NAS-Port-Type - * - * @param msg RADIUS request message to send - * @return response, NULL if timed out/verification failed - */ - radius_message_t* (*request)(radius_client_t *this, radius_message_t *msg); - - /** - * Get the EAP MSK after successful RADIUS authentication. - * - * @return MSK, allocated - */ - chunk_t (*get_msk)(radius_client_t *this); - - /** - * Destroy the client, release the socket. - */ - void (*destroy)(radius_client_t *this); -}; - -/** - * Create a RADIUS client. - * - * @return radius_client_t object - */ -radius_client_t *radius_client_create(); - -#endif /** RADIUS_CLIENT_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_message.c b/src/libcharon/plugins/eap_radius/radius_message.c deleted file mode 100644 index 23a29b772..000000000 --- a/src/libcharon/plugins/eap_radius/radius_message.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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 "radius_message.h" - -#include <daemon.h> -#include <crypto/hashers/hasher.h> - -typedef struct private_radius_message_t private_radius_message_t; -typedef struct rmsg_t rmsg_t; -typedef struct rattr_t rattr_t; - -/** - * RADIUS message header - */ -struct rmsg_t { - /** message code, radius_message_code_t */ - u_int8_t code; - /** message identifier */ - u_int8_t identifier; - /** length of Code, Identifier, Length, Authenticator and Attributes */ - u_int16_t length; - /** message authenticator, MD5 hash */ - u_int8_t authenticator[HASH_SIZE_MD5]; - /** variable list of packed attributes */ - u_int8_t attributes[]; -} __attribute__((packed)); - -/** - * RADIUS message attribute. - */ -struct rattr_t { - /** attribute type, radius_attribute_type_t */ - u_int8_t type; - /** length of the attriubte, including the Type, Length and Value fields */ - u_int8_t length; - /** variable length attribute value */ - u_int8_t value[]; -} __attribute__((packed)); - -/** - * Private data of an radius_message_t object. - */ -struct private_radius_message_t { - - /** - * Public radius_message_t interface. - */ - radius_message_t public; - - /** - * message data, allocated - */ - rmsg_t *msg; -}; - -ENUM_BEGIN(radius_message_code_names, RMC_ACCESS_REQUEST, RMC_ACCOUNTING_RESPONSE, - "Access-Request", - "Access-Accept", - "Access-Reject", - "Accounting-Request", - "Accounting-Response"); -ENUM_NEXT(radius_message_code_names, RMC_ACCESS_CHALLENGE, RMC_ACCESS_CHALLENGE, RMC_ACCOUNTING_RESPONSE, - "Access-Challenge"); -ENUM_END(radius_message_code_names, RMC_ACCESS_CHALLENGE); - -ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX, - "User-Name", - "User-Password", - "CHAP-Password", - "NAS-IP-Address", - "NAS-Port", - "Service-Type", - "Framed-Protocol", - "Framed-IP-Address", - "Framed-IP-Netmask", - "Framed-Routing", - "Filter-Id", - "Framed-MTU", - "Framed-Compression", - "Login-IP-Host", - "Login-Service", - "Login-TCP-Port", - "Unassigned", - "Reply-Message", - "Callback-Number", - "Callback-Id", - "Unassigned", - "Framed-Route", - "Framed-IPX-Network", - "State", - "Class", - "Vendor-Specific", - "Session-Timeout", - "Idle-Timeout", - "Termination-Action", - "Called-Station-Id", - "Calling-Station-Id", - "NAS-Identifier", - "Proxy-State", - "Login-LAT-Service", - "Login-LAT-Node", - "Login-LAT-Group", - "Framed-AppleTalk-Link", - "Framed-AppleTalk-Network", - "Framed-AppleTalk-Zone", - "Acct-Status-Type", - "Acct-Delay-Time", - "Acct-Input-Octets", - "Acct-Output-Octets", - "Acct-Session-Id", - "Acct-Authentic", - "Acct-Session-Time", - "Acct-Input-Packets", - "Acct-Output-Packets", - "Acct-Terminate-Cause", - "Acct-Multi-Session-Id", - "Acct-Link-Count", - "Acct-Input-Gigawords", - "Acct-Output-Gigawords", - "Unassigned", - "Event-Timestamp", - "Egress-VLANID", - "Ingress-Filters", - "Egress-VLAN-Name", - "User-Priority-Table", - "CHAP-Challenge", - "NAS-Port-Type", - "Port-Limit", - "Login-LAT-Port", - "Tunnel-Type", - "Tunnel-Medium-Type", - "Tunnel-Client-Endpoint", - "Tunnel-Server-Endpoint", - "Acct-Tunnel-Connection", - "Tunnel-Password", - "ARAP-Password", - "ARAP-Features", - "ARAP-Zone-Access", - "ARAP-Security", - "ARAP-Security-Data", - "Password-Retry", - "Prompt", - "Connect-Info", - "Configuration-Token", - "EAP-Message", - "Message-Authenticator", - "Tunnel-Private-Group-ID", - "Tunnel-Assignment-ID", - "Tunnel-Preference", - "ARAP-Challenge-Response", - "Acct-Interim-Interval", - "Acct-Tunnel-Packets-Lost", - "NAS-Port-Id", - "Framed-Pool", - "CUI", - "Tunnel-Client-Auth-ID", - "Tunnel-Server-Auth-ID", - "NAS-Filter-Rule", - "Unassigned", - "Originating-Line-Info", - "NAS-IPv6-Address", - "Framed-Interface-Id", - "Framed-IPv6-Prefix", - "Login-IPv6-Host", - "Framed-IPv6-Route", - "Framed-IPv6-Pool", - "Error-Cause", - "EAP-Key-Name", - "Digest-Response", - "Digest-Realm", - "Digest-Nonce", - "Digest-Response-Auth", - "Digest-Nextnonce", - "Digest-Method", - "Digest-URI", - "Digest-Qop", - "Digest-Algorithm", - "Digest-Entity-Body-Hash", - "Digest-CNonce", - "Digest-Nonce-Count", - "Digest-Username", - "Digest-Opaque", - "Digest-Auth-Param", - "Digest-AKA-Auts", - "Digest-Domain", - "Digest-Stale", - "Digest-HA1", - "SIP-AOR", - "Delegated-IPv6-Prefix", - "MIP6-Feature-Vector", - "MIP6-Home-Link-Prefix"); - -/** - * Attribute enumerator implementation - */ -typedef struct { - /** implements enumerator interface */ - enumerator_t public; - /** currently pointing attribute */ - rattr_t *next; - /** bytes left */ - int left; -} attribute_enumerator_t; - -METHOD(enumerator_t, attribute_enumerate, bool, - attribute_enumerator_t *this, int *type, chunk_t *data) -{ - if (this->left == 0) - { - return FALSE; - } - if (this->left < sizeof(rattr_t) || - this->left < this->next->length) - { - DBG1(DBG_IKE, "RADIUS message truncated"); - return FALSE; - } - *type = this->next->type; - data->ptr = this->next->value; - data->len = this->next->length - sizeof(rattr_t); - this->left -= this->next->length; - this->next = ((void*)this->next) + this->next->length; - return TRUE; -} - -METHOD(radius_message_t, create_enumerator, enumerator_t*, - private_radius_message_t *this) -{ - attribute_enumerator_t *e; - - if (ntohs(this->msg->length) < sizeof(rmsg_t) + sizeof(rattr_t)) - { - return enumerator_create_empty(); - } - INIT(e, - .public = { - .enumerate = (void*)_attribute_enumerate, - .destroy = (void*)free, - }, - .next = (rattr_t*)this->msg->attributes, - .left = ntohs(this->msg->length) - sizeof(rmsg_t), - ); - return &e->public; -} - -METHOD(radius_message_t, add, void, - private_radius_message_t *this, radius_attribute_type_t type, chunk_t data) -{ - rattr_t *attribute; - - data.len = min(data.len, 253); - this->msg = realloc(this->msg, - ntohs(this->msg->length) + sizeof(rattr_t) + data.len); - attribute = ((void*)this->msg) + ntohs(this->msg->length); - attribute->type = type; - attribute->length = data.len + sizeof(rattr_t); - memcpy(attribute->value, data.ptr, data.len); - this->msg->length = htons(ntohs(this->msg->length) + attribute->length); -} - -METHOD(radius_message_t, sign, void, - private_radius_message_t *this, rng_t *rng, signer_t *signer) -{ - char buf[HASH_SIZE_MD5]; - - /* build Request-Authenticator */ - rng->get_bytes(rng, HASH_SIZE_MD5, this->msg->authenticator); - - /* build Message-Authenticator attribute, using 16 null bytes */ - memset(buf, 0, sizeof(buf)); - add(this, RAT_MESSAGE_AUTHENTICATOR, chunk_create(buf, sizeof(buf))); - signer->get_signature(signer, - chunk_create((u_char*)this->msg, ntohs(this->msg->length)), - ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5); -} - -METHOD(radius_message_t, verify, bool, - private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer) -{ - char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5]; - enumerator_t *enumerator; - int type; - chunk_t data, msg; - bool has_eap = FALSE, has_auth = FALSE; - - /* replace Response by Request Authenticator for verification */ - memcpy(res_auth, this->msg->authenticator, HASH_SIZE_MD5); - memcpy(this->msg->authenticator, req_auth, HASH_SIZE_MD5); - msg = chunk_create((u_char*)this->msg, ntohs(this->msg->length)); - - /* verify Response-Authenticator */ - hasher->get_hash(hasher, msg, NULL); - hasher->get_hash(hasher, secret, buf); - if (!memeq(buf, res_auth, HASH_SIZE_MD5)) - { - DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed"); - return FALSE; - } - - /* verify Message-Authenticator attribute */ - enumerator = create_enumerator(this); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_MESSAGE_AUTHENTICATOR) - { - if (data.len != HASH_SIZE_MD5) - { - DBG1(DBG_CFG, "RADIUS Message-Authenticator invalid length"); - enumerator->destroy(enumerator); - return FALSE; - } - memcpy(buf, data.ptr, data.len); - memset(data.ptr, 0, data.len); - if (signer->verify_signature(signer, msg, - chunk_create(buf, sizeof(buf)))) - { - /* restore Message-Authenticator */ - memcpy(data.ptr, buf, data.len); - has_auth = TRUE; - break; - } - else - { - DBG1(DBG_CFG, "RADIUS Message-Authenticator verification failed"); - enumerator->destroy(enumerator); - return FALSE; - } - } - else if (type == RAT_EAP_MESSAGE) - { - has_eap = TRUE; - } - } - enumerator->destroy(enumerator); - /* restore Response-Authenticator */ - memcpy(this->msg->authenticator, res_auth, HASH_SIZE_MD5); - - if (has_eap && !has_auth) - { /* Message-Authenticator is required if we have an EAP-Message */ - DBG1(DBG_CFG, "RADIUS Message-Authenticator attribute missing"); - return FALSE; - } - return TRUE; -} - -METHOD(radius_message_t, get_code, radius_message_code_t, - private_radius_message_t *this) -{ - return this->msg->code; -} - -METHOD(radius_message_t, get_identifier, u_int8_t, - private_radius_message_t *this) -{ - return this->msg->identifier; -} - -METHOD(radius_message_t, set_identifier, void, - private_radius_message_t *this, u_int8_t identifier) -{ - this->msg->identifier = identifier; -} - -METHOD(radius_message_t, get_authenticator, u_int8_t*, - private_radius_message_t *this) -{ - return this->msg->authenticator; -} - - -METHOD(radius_message_t, get_encoding, chunk_t, - private_radius_message_t *this) -{ - return chunk_create((u_char*)this->msg, ntohs(this->msg->length)); -} - -METHOD(radius_message_t, destroy, void, - private_radius_message_t *this) -{ - free(this->msg); - free(this); -} - -/** - * Generic constructor - */ -static private_radius_message_t *radius_message_create() -{ - private_radius_message_t *this; - - INIT(this, - .public = { - .create_enumerator = _create_enumerator, - .add = _add, - .get_code = _get_code, - .get_identifier = _get_identifier, - .set_identifier = _set_identifier, - .get_authenticator = _get_authenticator, - .get_encoding = _get_encoding, - .sign = _sign, - .verify = _verify, - .destroy = _destroy, - }, - ); - - return this; -} - -/** - * See header - */ -radius_message_t *radius_message_create_request() -{ - private_radius_message_t *this = radius_message_create(); - - INIT(this->msg, - .code = RMC_ACCESS_REQUEST, - .identifier = 0, - .length = htons(sizeof(rmsg_t)), - ); - - return &this->public; -} - -/** - * See header - */ -radius_message_t *radius_message_parse_response(chunk_t data) -{ - private_radius_message_t *this = radius_message_create(); - - this->msg = malloc(data.len); - memcpy(this->msg, data.ptr, data.len); - if (data.len < sizeof(rmsg_t) || - ntohs(this->msg->length) != data.len) - { - DBG1(DBG_IKE, "RADIUS message has invalid length"); - destroy(this); - return NULL; - } - return &this->public; -} - diff --git a/src/libcharon/plugins/eap_radius/radius_message.h b/src/libcharon/plugins/eap_radius/radius_message.h deleted file mode 100644 index 266839d3b..000000000 --- a/src/libcharon/plugins/eap_radius/radius_message.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * 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 radius_message radius_message - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_MESSAGE_H_ -#define RADIUS_MESSAGE_H_ - -#include <library.h> - -typedef struct radius_message_t radius_message_t; -typedef enum radius_message_code_t radius_message_code_t; -typedef enum radius_attribute_type_t radius_attribute_type_t; - -/** - * RADIUS Message Codes. - */ -enum radius_message_code_t { - RMC_ACCESS_REQUEST = 1, - RMC_ACCESS_ACCEPT = 2, - RMC_ACCESS_REJECT = 3, - RMC_ACCOUNTING_REQUEST = 4, - RMC_ACCOUNTING_RESPONSE = 5, - RMC_ACCESS_CHALLENGE = 11, -}; - -/** - * Enum names for radius_attribute_type_t. - */ -extern enum_name_t *radius_message_code_names; - -/** - * RADIUS Attribute Types. - */ -enum radius_attribute_type_t { - RAT_USER_NAME = 1, - RAT_USER_PASSWORD = 2, - RAT_CHAP_PASSWORD = 3, - RAT_NAS_IP_ADDRESS = 4, - RAT_NAS_PORT = 5, - RAT_SERVICE_TYPE = 6, - RAT_FRAMED_PROTOCOL = 7, - RAT_FRAMED_IP_ADDRESS = 8, - RAT_FRAMED_IP_NETMASK = 9, - RAT_FRAMED_ROUTING = 10, - RAT_FILTER_ID = 11, - RAT_FRAMED_MTU = 12, - RAT_FRAMED_COMPRESSION = 13, - RAT_LOGIN_IP_HOST = 14, - RAT_LOGIN_SERVICE = 15, - RAT_LOGIN_TCP_PORT = 16, - RAT_REPLY_MESSAGE = 18, - RAT_CALLBACK_NUMBER = 19, - RAT_CALLBACK_ID = 20, - RAT_FRAMED_ROUTE = 22, - RAT_FRAMED_IPX_NETWORK = 23, - RAT_STATE = 24, - RAT_CLASS = 25, - RAT_VENDOR_SPECIFIC = 26, - RAT_SESSION_TIMEOUT = 27, - RAT_IDLE_TIMEOUT = 28, - RAT_TERMINATION_ACTION = 29, - RAT_CALLED_STATION_ID = 30, - RAT_CALLING_STATION_ID = 31, - RAT_NAS_IDENTIFIER = 32, - RAT_PROXY_STATE = 33, - RAT_LOGIN_LAT_SERVICE = 34, - RAT_LOGIN_LAT_NODE = 35, - RAT_LOGIN_LAT_GROUP = 36, - RAT_FRAMED_APPLETALK_LINK = 37, - RAT_FRAMED_APPLETALK_NETWORK = 38, - RAT_FRAMED_APPLETALK_ZONE = 39, - RAT_ACCT_STATUS_TYPE = 40, - RAT_ACCT_DELAY_TIME = 41, - RAT_ACCT_INPUT_OCTETS = 42, - RAT_ACCT_OUTPUT_OCTETS = 43, - RAT_ACCT_SESSION_ID = 44, - RAT_ACCT_AUTHENTIC = 45, - RAT_ACCT_SESSION_TIME = 46, - RAT_ACCT_INPUT_PACKETS = 47, - RAT_ACCT_OUTPUT_PACKETS = 48, - RAT_ACCT_TERMINATE_CAUSE = 49, - RAT_ACCT_MULTI_SESSION_ID = 50, - RAT_ACCT_LINK_COUNT = 51, - RAT_ACCT_INPUT_GIGAWORDS = 52, - RAT_ACCT_OUTPUT_GIGAWORDS = 53, - RAT_EVENT_TIMESTAMP = 55, - RAT_EGRESS_VLANID = 56, - RAT_INGRESS_FILTERS = 57, - RAT_EGRESS_VLAN_NAME = 58, - RAT_USER_PRIORITY_TABLE = 59, - RAT_CHAP_CHALLENGE = 60, - RAT_NAS_PORT_TYPE = 61, - RAT_PORT_LIMIT = 62, - RAT_LOGIN_LAT_PORT = 63, - RAT_TUNNEL_TYPE = 64, - RAT_TUNNEL_MEDIUM_TYPE = 65, - RAT_TUNNEL_CLIENT_ENDPOINT = 66, - RAT_TUNNEL_SERVER_ENDPOINT = 67, - RAT_ACCT_TUNNEL_CONNECTION = 68, - RAT_TUNNEL_PASSWORD = 69, - RAT_ARAP_PASSWORD = 70, - RAT_ARAP_FEATURES = 71, - RAT_ARAP_ZONE_ACCESS = 72, - RAT_ARAP_SECURITY = 73, - RAT_ARAP_SECURITY_DATA = 74, - RAT_PASSWORD_RETRY = 75, - RAT_PROMPT = 76, - RAT_CONNECT_INFO = 77, - RAT_CONFIGURATION_TOKEN = 78, - RAT_EAP_MESSAGE = 79, - RAT_MESSAGE_AUTHENTICATOR = 80, - RAT_TUNNEL_PRIVATE_GROUP_ID = 81, - RAT_TUNNEL_ASSIGNMENT_ID = 82, - RAT_TUNNEL_PREFERENCE = 83, - RAT_ARAP_CHALLENGE_RESPONSE = 84, - RAT_ACCT_INTERIM_INTERVAL = 85, - RAT_ACCT_TUNNEL_PACKETS_LOST = 86, - RAT_NAS_PORT_ID = 87, - RAT_FRAMED_POOL = 88, - RAT_CUI = 89, - RAT_TUNNEL_CLIENT_AUTH_ID = 90, - RAT_TUNNEL_SERVER_AUTH_ID = 91, - RAT_NAS_FILTER_RULE = 92, - RAT_UNASSIGNED = 93, - RAT_ORIGINATING_LINE_INFO = 94, - RAT_NAS_IPV6_ADDRESS = 95, - RAT_FRAMED_INTERFACE_ID = 96, - RAT_FRAMED_IPV6_PREFIX = 97, - RAT_LOGIN_IPV6_HOST = 98, - RAT_FRAMED_IPV6_ROUTE = 99, - RAT_FRAMED_IPV6_POOL = 100, - RAT_ERROR_CAUSE = 101, - RAT_EAP_KEY_NAME = 102, - RAT_DIGEST_RESPONSE = 103, - RAT_DIGEST_REALM = 104, - RAT_DIGEST_NONCE = 105, - RAT_DIGEST_RESPONSE_AUTH = 106, - RAT_DIGEST_NEXTNONCE = 107, - RAT_DIGEST_METHOD = 108, - RAT_DIGEST_URI = 109, - RAT_DIGEST_QOP = 110, - RAT_DIGEST_ALGORITHM = 111, - RAT_DIGEST_ENTITY_BODY_HASH = 112, - RAT_DIGEST_CNONCE = 113, - RAT_DIGEST_NONCE_COUNT = 114, - RAT_DIGEST_USERNAME = 115, - RAT_DIGEST_OPAQUE = 116, - RAT_DIGEST_AUTH_PARAM = 117, - RAT_DIGEST_AKA_AUTS = 118, - RAT_DIGEST_DOMAIN = 119, - RAT_DIGEST_STALE = 120, - RAT_DIGEST_HA1 = 121, - RAT_SIP_AOR = 122, - RAT_DELEGATED_IPV6_PREFIX = 123, - RAT_MIP6_FEATURE_VECTOR = 124, - RAT_MIP6_HOME_LINK_PREFIX = 125, -}; - -/** - * Enum names for radius_attribute_type_t. - */ -extern enum_name_t *radius_attribute_type_names; - -/** - * A RADIUS message, contains attributes. - */ -struct radius_message_t { - - /** - * Create an enumerator over contained RADIUS attributes. - * - * @return enumerator over (int type, chunk_t data) - */ - enumerator_t* (*create_enumerator)(radius_message_t *this); - - /** - * Add a RADIUS attribute to the message. - * - * @param type type of attribute to add - * @param attribute data, gets cloned - */ - void (*add)(radius_message_t *this, radius_attribute_type_t type, - chunk_t data); - - /** - * Get the message type (code). - * - * @return message code - */ - radius_message_code_t (*get_code)(radius_message_t *this); - - /** - * Get the message identifier. - * - * @return message identifier - */ - u_int8_t (*get_identifier)(radius_message_t *this); - - /** - * Set the message identifier. - * - * @param identifier message identifier - */ - void (*set_identifier)(radius_message_t *this, u_int8_t identifier); - - /** - * Get the 16 byte authenticator. - * - * @return pointer to the Authenticator field - */ - u_int8_t* (*get_authenticator)(radius_message_t *this); - - /** - * Get the RADIUS message in its encoded form. - * - * @return chunk pointing to internal RADIUS message. - */ - chunk_t (*get_encoding)(radius_message_t *this); - - /** - * Calculate and add the Message-Authenticator attribute to the message. - * - * @param rng RNG to create Request-Authenticator - * @param signer HMAC-MD5 signer with secret set - */ - void (*sign)(radius_message_t *this, rng_t *rng, signer_t *signer); - - /** - * Verify the integrity of a received RADIUS response. - * - * @param req_auth 16 byte Authenticator of the corresponding request - * @param secret shared RADIUS secret - * @param hasher hasher to verify Response-Authenticator - * @param signer signer to verify Message-Authenticator attribute - */ - bool (*verify)(radius_message_t *this, u_int8_t *req_auth, chunk_t secret, - hasher_t *hasher, signer_t *signer); - - /** - * Destroy the message. - */ - void (*destroy)(radius_message_t *this); -}; - -/** - * Create an empty RADIUS request message (RMT_ACCESS_REQUEST). - * - * @return radius_message_t object - */ -radius_message_t *radius_message_create_request(); - -/** - * Parse and verify a recevied RADIUS response. - * - * @param data received message data - * @return radius_message_t object, NULL if length invalid - */ -radius_message_t *radius_message_parse_response(chunk_t data); - -#endif /** RADIUS_MESSAGE_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c deleted file mode 100644 index 3baf39807..000000000 --- a/src/libcharon/plugins/eap_radius/radius_server.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 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 "radius_server.h" - -#include <threading/mutex.h> -#include <threading/condvar.h> -#include <utils/linked_list.h> - -typedef struct private_radius_server_t private_radius_server_t; - -/** - * Private data of an radius_server_t object. - */ -struct private_radius_server_t { - - /** - * Public radius_server_t interface. - */ - radius_server_t public; - - /** - * list of radius sockets, as radius_socket_t - */ - linked_list_t *sockets; - - /** - * Total number of sockets, in list + currently in use - */ - int socket_count; - - /** - * mutex to lock sockets list - */ - mutex_t *mutex; - - /** - * condvar to wait for sockets - */ - condvar_t *condvar; - - /** - * Server name - */ - char *name; - - /** - * NAS-Identifier - */ - chunk_t nas_identifier; - - /** - * Preference boost for this server - */ - int preference; - - /** - * Is the server currently reachable - */ - bool reachable; - - /** - * Retry counter for unreachable servers - */ - int retry; - - /** - * reference count - */ - refcount_t ref; -}; - -METHOD(radius_server_t, get_socket, radius_socket_t*, - private_radius_server_t *this) -{ - radius_socket_t *skt; - - this->mutex->lock(this->mutex); - while (this->sockets->remove_first(this->sockets, (void**)&skt) != SUCCESS) - { - this->condvar->wait(this->condvar, this->mutex); - } - this->mutex->unlock(this->mutex); - return skt; -} - -METHOD(radius_server_t, put_socket, void, - private_radius_server_t *this, radius_socket_t *skt, bool result) -{ - this->mutex->lock(this->mutex); - this->sockets->insert_last(this->sockets, skt); - this->mutex->unlock(this->mutex); - this->condvar->signal(this->condvar); - this->reachable = result; -} - -METHOD(radius_server_t, get_nas_identifier, chunk_t, - private_radius_server_t *this) -{ - return this->nas_identifier; -} - -METHOD(radius_server_t, get_preference, int, - private_radius_server_t *this) -{ - int pref; - - if (this->socket_count == 0) - { /* don't have sockets, huh? */ - return -1; - } - /* calculate preference between 0-100 + boost */ - pref = this->preference; - pref += this->sockets->get_count(this->sockets) * 100 / this->socket_count; - if (this->reachable) - { /* reachable server get a boost: pref = 110-210 + boost */ - return pref + 110; - } - /* Not reachable. Increase preference randomly to let it retry from - * time to time, especially if other servers have high load. */ - this->retry++; - if (this->retry % 128 == 0) - { /* every 64th request gets 210, same as unloaded reachable */ - return pref + 110; - } - if (this->retry % 32 == 0) - { /* every 32th request gets 190, wins against average loaded */ - return pref + 90; - } - if (this->retry % 8 == 0) - { /* every 8th request gets 110, same as server under load */ - return pref + 10; - } - /* other get ~100, less than fully loaded */ - return pref; -} - -METHOD(radius_server_t, get_name, char*, - private_radius_server_t *this) -{ - return this->name; -} - -METHOD(radius_server_t, get_ref, radius_server_t*, - private_radius_server_t *this) -{ - ref_get(&this->ref); - return &this->public; -} - - -METHOD(radius_server_t, destroy, void, - private_radius_server_t *this) -{ - if (ref_put(&this->ref)) - { - this->mutex->destroy(this->mutex); - this->condvar->destroy(this->condvar); - this->sockets->destroy_offset(this->sockets, - offsetof(radius_socket_t, destroy)); - free(this); - } -} - -/** - * See header - */ -radius_server_t *radius_server_create(char *name, char *address, u_int16_t port, - char *nas_identifier, char *secret, int sockets, int preference) -{ - private_radius_server_t *this; - radius_socket_t *socket; - - INIT(this, - .public = { - .get_socket = _get_socket, - .put_socket = _put_socket, - .get_nas_identifier = _get_nas_identifier, - .get_preference = _get_preference, - .get_name = _get_name, - .get_ref = _get_ref, - .destroy = _destroy, - }, - .reachable = TRUE, - .nas_identifier = chunk_create(nas_identifier, strlen(nas_identifier)), - .socket_count = sockets, - .sockets = linked_list_create(), - .mutex = mutex_create(MUTEX_TYPE_DEFAULT), - .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), - .name = name, - .preference = preference, - .ref = 1, - ); - - while (sockets--) - { - socket = radius_socket_create(address, port, - chunk_create(secret, strlen(secret))); - if (!socket) - { - destroy(this); - return NULL; - } - this->sockets->insert_last(this->sockets, socket); - } - return &this->public; -} diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h deleted file mode 100644 index c59361c49..000000000 --- a/src/libcharon/plugins/eap_radius/radius_server.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 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 radius_server radius_server - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_SERVER_H_ -#define RADIUS_SERVER_H_ - -typedef struct radius_server_t radius_server_t; - -#include "radius_socket.h" - -/** - * RADIUS server configuration. - */ -struct radius_server_t { - - /** - * Get a RADIUS socket from the pool to communicate with this server. - * - * @return RADIUS socket - */ - radius_socket_t* (*get_socket)(radius_server_t *this); - - /** - * Release a socket to the pool after use. - * - * @param skt RADIUS socket to release - * @param result result of the socket use, TRUE for success - */ - void (*put_socket)(radius_server_t *this, radius_socket_t *skt, bool result); - - /** - * Get the NAS-Identifier to use with this server. - * - * @return NAS-Identifier, internal data - */ - chunk_t (*get_nas_identifier)(radius_server_t *this); - - /** - * Get the preference of this server. - * - * Based on the available sockets and the server reachability a preference - * value is calculated: better servers return a higher value. - */ - int (*get_preference)(radius_server_t *this); - - /** - * Get the name of the RADIUS server. - * - * @return server name - */ - char* (*get_name)(radius_server_t *this); - - /** - * Increase reference count of this server. - * - * @return this - */ - radius_server_t* (*get_ref)(radius_server_t *this); - - /** - * Destroy a radius_server_t. - */ - void (*destroy)(radius_server_t *this); -}; - -/** - * Create a radius_server instance. - * - * @param name server name - * @param address server address - * @param port server port - * @param nas_identifier NAS-Identifier to use with this server - * @param secret secret to use with this server - * @param sockets number of sockets to create in pool - * @param preference preference boost for this server - */ -radius_server_t *radius_server_create(char *name, char *address, u_int16_t port, - char *nas_identifier, char *secret, int sockets, int preference); - -#endif /** RADIUS_SERVER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_socket.c b/src/libcharon/plugins/eap_radius/radius_socket.c deleted file mode 100644 index b3229c288..000000000 --- a/src/libcharon/plugins/eap_radius/radius_socket.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 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 "radius_socket.h" - -#include <errno.h> -#include <unistd.h> - -#include <debug.h> - -/** - * Vendor-Id of Microsoft specific attributes - */ -#define VENDOR_ID_MICROSOFT 311 - -/** - * Microsoft specific vendor attributes - */ -#define MS_MPPE_SEND_KEY 16 -#define MS_MPPE_RECV_KEY 17 - -typedef struct private_radius_socket_t private_radius_socket_t; - -/** - * Private data of an radius_socket_t object. - */ -struct private_radius_socket_t { - - /** - * Public radius_socket_t interface. - */ - radius_socket_t public; - - /** - * socket file descriptor - */ - int fd; - - /** - * Server address - */ - char *address; - - /** - * Server port - */ - u_int16_t port; - - /** - * current RADIUS identifier - */ - u_int8_t identifier; - - /** - * hasher to use for response verification - */ - hasher_t *hasher; - - /** - * HMAC-MD5 signer to build Message-Authenticator attribute - */ - signer_t *signer; - - /** - * random number generator for RADIUS request authenticator - */ - rng_t *rng; - - /** - * RADIUS secret - */ - chunk_t secret; -}; - -/** - * Check or establish RADIUS connection - */ -static bool check_connection(private_radius_socket_t *this) -{ - if (this->fd == -1) - { - host_t *server; - - server = host_create_from_dns(this->address, AF_UNSPEC, this->port); - if (!server) - { - DBG1(DBG_CFG, "resolving RADIUS server address '%s' failed", - this->address); - return FALSE; - } - this->fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP); - if (this->fd == -1) - { - DBG1(DBG_CFG, "opening RADIUS socket for %#H failed: %s", - server, strerror(errno)); - server->destroy(server); - return FALSE; - } - if (connect(this->fd, server->get_sockaddr(server), - *server->get_sockaddr_len(server)) < 0) - { - DBG1(DBG_CFG, "connecting RADIUS socket to %#H failed: %s", - server, strerror(errno)); - server->destroy(server); - close(this->fd); - this->fd = -1; - return FALSE; - } - server->destroy(server); - } - return TRUE; -} - -METHOD(radius_socket_t, request, radius_message_t*, - private_radius_socket_t *this, radius_message_t *request) -{ - chunk_t data; - int i; - - /* set Message Identifier */ - request->set_identifier(request, this->identifier++); - /* sign the request */ - request->sign(request, this->rng, this->signer); - - if (!check_connection(this)) - { - return NULL; - } - - data = request->get_encoding(request); - /* timeout after 2, 3, 4, 5 seconds */ - for (i = 2; i <= 5; i++) - { - radius_message_t *response; - bool retransmit = FALSE; - struct timeval tv; - char buf[4096]; - fd_set fds; - int res; - - if (send(this->fd, data.ptr, data.len, 0) != data.len) - { - DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); - return NULL; - } - tv.tv_sec = i; - tv.tv_usec = 0; - - while (TRUE) - { - FD_ZERO(&fds); - FD_SET(this->fd, &fds); - res = select(this->fd + 1, &fds, NULL, NULL, &tv); - /* TODO: updated tv to time not waited. Linux does this for us. */ - if (res < 0) - { /* failed */ - DBG1(DBG_CFG, "waiting for RADIUS message failed: %s", - strerror(errno)); - break; - } - if (res == 0) - { /* timeout */ - DBG1(DBG_CFG, "retransmitting RADIUS message"); - retransmit = TRUE; - break; - } - res = recv(this->fd, buf, sizeof(buf), MSG_DONTWAIT); - if (res <= 0) - { - DBG1(DBG_CFG, "receiving RADIUS message failed: %s", - strerror(errno)); - break; - } - response = radius_message_parse_response(chunk_create(buf, res)); - if (response) - { - if (response->verify(response, - request->get_authenticator(request), this->secret, - this->hasher, this->signer)) - { - return response; - } - response->destroy(response); - } - DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); - } - if (!retransmit) - { - break; - } - } - DBG1(DBG_CFG, "RADIUS server is not responding"); - return NULL; -} - -/** - * Decrypt a MS-MPPE-Send/Recv-Key - */ -static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt, - chunk_t C, radius_message_t *request) -{ - chunk_t A, R, P, seed; - u_char *c, *p; - - /** - * From RFC2548 (encryption): - * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) - * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) - * . . . - * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) - */ - - if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5) - { - return chunk_empty; - } - - A = chunk_create((u_char*)&salt, sizeof(salt)); - R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); - P = chunk_alloca(C.len); - p = P.ptr; - c = C.ptr; - - seed = chunk_cata("cc", R, A); - - while (c < C.ptr + C.len) - { - /* b(i) = MD5(S + c(i-1)) */ - this->hasher->get_hash(this->hasher, this->secret, NULL); - this->hasher->get_hash(this->hasher, seed, p); - - /* p(i) = b(i) xor c(1) */ - memxor(p, c, HASH_SIZE_MD5); - - /* prepare next round */ - seed = chunk_create(c, HASH_SIZE_MD5); - c += HASH_SIZE_MD5; - p += HASH_SIZE_MD5; - } - - /* remove truncation, first byte is key length */ - if (*P.ptr >= P.len) - { /* decryption failed? */ - return chunk_empty; - } - return chunk_clone(chunk_create(P.ptr + 1, *P.ptr)); -} - -METHOD(radius_socket_t, decrypt_msk, chunk_t, - private_radius_socket_t *this, radius_message_t *request, - radius_message_t *response) -{ - struct { - u_int32_t id; - u_int8_t type; - u_int8_t length; - u_int16_t salt; - u_int8_t key[]; - } __attribute__((packed)) *mppe_key; - enumerator_t *enumerator; - chunk_t data, send = chunk_empty, recv = chunk_empty; - int type; - - enumerator = response->create_enumerator(response); - while (enumerator->enumerate(enumerator, &type, &data)) - { - if (type == RAT_VENDOR_SPECIFIC && - data.len > sizeof(*mppe_key)) - { - mppe_key = (void*)data.ptr; - if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT && - mppe_key->length == data.len - sizeof(mppe_key->id)) - { - data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key)); - if (mppe_key->type == MS_MPPE_SEND_KEY) - { - send = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - if (mppe_key->type == MS_MPPE_RECV_KEY) - { - recv = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - } - } - } - enumerator->destroy(enumerator); - if (send.ptr && recv.ptr) - { - return chunk_cat("mm", recv, send); - } - chunk_clear(&send); - chunk_clear(&recv); - return chunk_empty; -} - -METHOD(radius_socket_t, destroy, void, - private_radius_socket_t *this) -{ - DESTROY_IF(this->hasher); - DESTROY_IF(this->signer); - DESTROY_IF(this->rng); - if (this->fd != -1) - { - close(this->fd); - } - free(this); -} - -/** - * See header - */ -radius_socket_t *radius_socket_create(char *address, u_int16_t port, - chunk_t secret) -{ - private_radius_socket_t *this; - - INIT(this, - .public = { - .request = _request, - .decrypt_msk = _decrypt_msk, - .destroy = _destroy, - }, - .address = address, - .port = port, - .fd = -1, - ); - - this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128); - this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!this->hasher || !this->signer || !this->rng) - { - DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required"); - destroy(this); - return NULL; - } - this->secret = secret; - this->signer->set_key(this->signer, secret); - /* we use a random identifier, helps if we restart often */ - this->identifier = random(); - - return &this->public; -} diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h deleted file mode 100644 index 2875008eb..000000000 --- a/src/libcharon/plugins/eap_radius/radius_socket.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010 Martin Willi - * Copyright (C) 2010 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 radius_socket radius_socket - * @{ @ingroup eap_radius - */ - -#ifndef RADIUS_SOCKET_H_ -#define RADIUS_SOCKET_H_ - -typedef struct radius_socket_t radius_socket_t; - -#include "radius_message.h" - -#include <utils/host.h> - -/** - * RADIUS socket to a server. - */ -struct radius_socket_t { - - /** - * Send a RADIUS request, wait for response. - * - * The socket fills in RADIUS Message identifier, builds a - * Request-Authenticator and calculates the Message-Authenticator - * attribute. - * The received response gets verified using the Response-Identifier - * and the Message-Authenticator attribute. - * - * @param request request message - * @return response message, NULL if timed out - */ - radius_message_t* (*request)(radius_socket_t *this, - radius_message_t *request); - - /** - * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key. - * - * @param request associated RADIUS request message - * @param response RADIUS response message containing attributes - * @return allocated MSK, empty chunk if none found - */ - chunk_t (*decrypt_msk)(radius_socket_t *this, radius_message_t *request, - radius_message_t *response); - - /** - * Destroy a radius_socket_t. - */ - void (*destroy)(radius_socket_t *this); -}; - -/** - * Create a radius_socket instance. - * - * @param address server name - * @param port server port - * @param secret RADIUS secret - */ -radius_socket_t *radius_socket_create(char *address, u_int16_t port, - chunk_t secret); - -#endif /** RADIUS_SOCKET_H_ @}*/ diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in index b9ab6656b..d06929522 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c index 083bf73a3..1d1ab99e0 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c @@ -18,6 +18,7 @@ #include <daemon.h> #include <simaka_message.h> +#include <simaka_manager.h> /* number of tries we do authenticate */ #define MAX_TRIES 3 @@ -41,6 +42,11 @@ struct private_eap_sim_peer_t { eap_sim_peer_t public; /** + * SIM backend manager + */ + simaka_manager_t *mgr; + + /** * permanent ID of peer */ identification_t *permanent; @@ -116,7 +122,7 @@ static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, encoded = htons(code); message->add_attribute(message, AT_CLIENT_ERROR_CODE, chunk_create((char*)&encoded, sizeof(encoded))); - out = message->generate(message, chunk_empty); + out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); return out; } @@ -188,7 +194,7 @@ static status_t process_start(private_eap_sim_peer_t *this, switch (id_req) { case AT_ANY_ID_REQ: - this->reauth = charon->sim->card_get_reauth(charon->sim, + this->reauth = this->mgr->card_get_reauth(this->mgr, this->permanent, this->mk, &this->counter); if (this->reauth) { @@ -197,8 +203,8 @@ static status_t process_start(private_eap_sim_peer_t *this, } /* FALL */ case AT_FULLAUTH_ID_REQ: - this->pseudonym = charon->sim->card_get_pseudonym(charon->sim, - this->permanent); + this->pseudonym = this->mgr->card_get_pseudonym(this->mgr, + this->permanent); if (this->pseudonym) { id = this->pseudonym->get_encoding(this->pseudonym); @@ -228,7 +234,7 @@ static status_t process_start(private_eap_sim_peer_t *this, { message->add_attribute(message, AT_IDENTITY, id); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); return NEED_MORE; @@ -287,8 +293,8 @@ static status_t process_challenge(private_eap_sim_peer_t *this, sreses = sres = chunk_alloca(rands.len / 4); while (rands.len >= SIM_RAND_LEN) { - if (!charon->sim->card_get_triplet(charon->sim, this->permanent, - rands.ptr, sres.ptr, kc.ptr)) + if (!this->mgr->card_get_triplet(this->mgr, this->permanent, + rands.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); @@ -328,13 +334,13 @@ static status_t process_challenge(private_eap_sim_peer_t *this, case AT_NEXT_REAUTH_ID: this->counter = 0; id = identification_create_from_data(data); - charon->sim->card_set_reauth(charon->sim, this->permanent, id, - this->mk, this->counter); + this->mgr->card_set_reauth(this->mgr, this->permanent, id, + this->mk, this->counter); id->destroy(id); break; case AT_NEXT_PSEUDONYM: id = identification_create_from_data(data); - charon->sim->card_set_pseudonym(charon->sim, this->permanent, id); + this->mgr->card_set_pseudonym(this->mgr, this->permanent, id); id->destroy(id); break; default: @@ -346,7 +352,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, /* build response with AT_MAC, built over "EAP packet | n*SRES" */ message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_CHALLENGE, this->crypto); - *out = message->generate(message, sreses); + *out = eap_payload_create_data_own(message->generate(message, sreses)); message->destroy(message); return NEED_MORE; } @@ -443,13 +449,13 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, identification_t *reauth; reauth = identification_create_from_data(data); - charon->sim->card_set_reauth(charon->sim, this->permanent, reauth, - this->mk, this->counter); + this->mgr->card_set_reauth(this->mgr, this->permanent, reauth, + this->mk, this->counter); reauth->destroy(reauth); } } message->add_attribute(message, AT_COUNTER, counter); - *out = message->generate(message, nonce); + *out = eap_payload_create_data_own(message->generate(message, nonce)); message->destroy(message); return NEED_MORE; } @@ -500,7 +506,8 @@ static status_t process_notification(private_eap_sim_peer_t *this, { /* empty notification reply */ message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_NOTIFICATION, this->crypto); - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, + chunk_empty)); message->destroy(message); } else @@ -519,7 +526,7 @@ METHOD(eap_method_t, process, status_t, /* store received EAP message identifier */ this->identifier = in->get_identifier(in); - message = simaka_message_create_from_payload(in, this->crypto); + message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); @@ -633,7 +640,8 @@ eap_sim_peer_t *eap_sim_peer_create(identification_t *server, .destroy = _destroy, }, }, - .crypto = simaka_crypto_create(), + .crypto = simaka_crypto_create(EAP_SIM), + .mgr = lib->get(lib, "sim-manager"), ); if (!this->crypto) diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.h b/src/libcharon/plugins/eap_sim/eap_sim_peer.h index 89f81301e..ba72ce484 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_peer.h +++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.h @@ -27,9 +27,6 @@ typedef struct eap_sim_peer_t eap_sim_peer_t; /** * EAP-SIM peer implementation. - * - * This EAP-SIM module uses sim_card_t implementations for triplet calculation, - * found via the eap_sim_manager_t. */ struct eap_sim_peer_t { diff --git a/src/libcharon/plugins/eap_sim/eap_sim_plugin.c b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c index b15292544..5bc0af6bd 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_plugin.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c @@ -19,20 +19,61 @@ #include "eap_sim_peer.h" #include <daemon.h> +#include <simaka_manager.h> + +typedef struct private_eap_sim_plugin_t private_eap_sim_plugin_t; + +/** + * Private data of an eap_sim_plugin_t object. + */ +struct private_eap_sim_plugin_t { + + /** + * Public interface. + */ + eap_sim_plugin_t public; + + /** + * EAP-SIM backend manager + */ + simaka_manager_t *mgr; +}; METHOD(plugin_t, get_name, char*, - eap_sim_plugin_t *this) + private_eap_sim_plugin_t *this) { return "eap-sim"; } +METHOD(plugin_t, get_features, int, + private_eap_sim_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_PROVIDE(CUSTOM, "sim-manager"), + PLUGIN_CALLBACK(eap_method_register, eap_sim_server_create), + PLUGIN_PROVIDE(EAP_SERVER, EAP_SIM), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(PRF, PRF_FIPS_SHA1_160), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_SHA1_128), + PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16), + PLUGIN_CALLBACK(eap_method_register, eap_sim_peer_create), + PLUGIN_PROVIDE(EAP_PEER, EAP_SIM), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(PRF, PRF_FIPS_SHA1_160), + PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_SHA1_128), + PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, - eap_sim_plugin_t *this) + private_eap_sim_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_sim_server_create); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_sim_peer_create); + lib->set(lib, "sim-manager", NULL); + this->mgr->destroy(this->mgr); free(this); } @@ -41,21 +82,20 @@ METHOD(plugin_t, destroy, void, */ plugin_t *eap_sim_plugin_create() { - eap_sim_plugin_t *this; + private_eap_sim_plugin_t *this; INIT(this, - .plugin = { - .get_name = _get_name, - .reload = (void*)return_false, - .destroy = _destroy, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, }, + .mgr = simaka_manager_create(), ); + lib->set(lib, "sim-manager", this->mgr); - charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER, - (eap_constructor_t)eap_sim_server_create); - charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_PEER, - (eap_constructor_t)eap_sim_peer_create); - - return &this->plugin; + return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_sim/eap_sim_plugin.h b/src/libcharon/plugins/eap_sim/eap_sim_plugin.h index 4e10380c4..0c71ca548 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_plugin.h +++ b/src/libcharon/plugins/eap_sim/eap_sim_plugin.h @@ -30,6 +30,11 @@ typedef struct eap_sim_plugin_t eap_sim_plugin_t; /** * EAP-SIM plugin. + * + * This plugin implements the protocol level of EAP-SIM and uses simaka_card_t + * and simaka_provider_t backends to provide triplets. It registers a + * simaka_manager_t on the library as "sim-manager", other plugins can use it + * to provide the required backends. */ struct eap_sim_plugin_t { diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c index d1dfde5d6..e0f7e92ad 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_server.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c @@ -19,6 +19,7 @@ #include <simaka_message.h> #include <simaka_crypto.h> +#include <simaka_manager.h> /* number of triplets for one authentication */ #define TRIPLET_COUNT 3 @@ -39,6 +40,11 @@ struct private_eap_sim_server_t { eap_sim_server_t public; /** + * SIM backend manager + */ + simaka_manager_t *mgr; + + /** * permanent ID of peer */ identification_t *permanent; @@ -127,7 +133,7 @@ METHOD(eap_method_t, initiate, status_t, { message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); this->pending = SIM_START; @@ -163,14 +169,14 @@ static status_t reauthenticate(private_eap_sim_server_t *this, SIM_REAUTHENTICATION, this->crypto); message->add_attribute(message, AT_COUNTER, this->counter); message->add_attribute(message, AT_NONCE_S, this->nonce); - next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk); + next = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk); if (next) { message->add_attribute(message, AT_NEXT_REAUTH_ID, next->get_encoding(next)); next->destroy(next); } - *out = message->generate(message, chunk_empty); + *out = eap_payload_create_data_own(message->generate(message, chunk_empty)); message->destroy(message); this->pending = SIM_REAUTHENTICATION; @@ -298,8 +304,8 @@ static status_t process_start(private_eap_sim_server_t *this, char mk[HASH_SIZE_SHA1]; u_int16_t counter; - permanent = charon->sim->provider_is_reauth(charon->sim, id, - mk, &counter); + permanent = this->mgr->provider_is_reauth(this->mgr, id, + mk, &counter); if (permanent) { this->permanent->destroy(this->permanent); @@ -315,7 +321,7 @@ static status_t process_start(private_eap_sim_server_t *this, } if (this->use_pseudonym) { - permanent = charon->sim->provider_is_pseudonym(charon->sim, id); + permanent = this->mgr->provider_is_pseudonym(this->mgr, id); if (permanent) { this->permanent->destroy(this->permanent); @@ -348,8 +354,8 @@ static status_t process_start(private_eap_sim_server_t *this, rands.len = kcs.len = sreses.len = 0; for (i = 0; i < TRIPLET_COUNT; i++) { - if (!charon->sim->provider_get_triplet(charon->sim, this->permanent, - rand.ptr, sres.ptr, kc.ptr)) + if (!this->mgr->provider_get_triplet(this->mgr, this->permanent, + rand.ptr, sres.ptr, kc.ptr)) { if (this->use_pseudonym) { @@ -386,24 +392,21 @@ static status_t process_start(private_eap_sim_server_t *this, message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, SIM_CHALLENGE, this->crypto); message->add_attribute(message, AT_RAND, rands); - id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr); + id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr); if (id) { message->add_attribute(message, AT_NEXT_REAUTH_ID, id->get_encoding(id)); id->destroy(id); } - else + id = this->mgr->provider_gen_pseudonym(this->mgr, this->permanent); + if (id) { - id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent); - if (id) - { - message->add_attribute(message, AT_NEXT_PSEUDONYM, - id->get_encoding(id)); - id->destroy(id); - } + message->add_attribute(message, AT_NEXT_PSEUDONYM, + id->get_encoding(id)); + id->destroy(id); } - *out = message->generate(message, nonce); + *out = eap_payload_create_data_own(message->generate(message, nonce)); message->destroy(message); free(mk.ptr); @@ -483,7 +486,7 @@ METHOD(eap_method_t, process, status_t, simaka_message_t *message; status_t status; - message = simaka_message_create_from_payload(in, this->crypto); + message = simaka_message_create_from_payload(in->get_data(in), this->crypto); if (!message) { return FAILED; @@ -588,7 +591,8 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server, .destroy = _destroy, }, }, - .crypto = simaka_crypto_create(), + .crypto = simaka_crypto_create(EAP_SIM), + .mgr = lib->get(lib, "sim-manager"), ); if (!this->crypto) diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.h b/src/libcharon/plugins/eap_sim/eap_sim_server.h index 978e1e1e9..c0ed64ff2 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_server.h +++ b/src/libcharon/plugins/eap_sim/eap_sim_server.h @@ -27,9 +27,6 @@ typedef struct eap_sim_server_t eap_sim_server_t; /** * EAP-SIM server implementation. - * - * This EAP-SIM module uses sim_provider_t implementations for triplet - * calculation, found via the eap_sim_manager_t. */ struct eap_sim_server_t { diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am index 2b59a7c88..d76cdc5ca 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.am +++ b/src/libcharon/plugins/eap_sim_file/Makefile.am @@ -1,6 +1,6 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" @@ -8,6 +8,7 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la else plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la +libstrongswan_eap_sim_file_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_sim_file_la_SOURCES = \ diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index 5662a1c53..bebf62e5b 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -74,7 +74,8 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_sim_file_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_eap_sim_file_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la am_libstrongswan_eap_sim_file_la_OBJECTS = eap_sim_file_plugin.lo \ eap_sim_file_card.lo eap_sim_file_provider.lo \ eap_sim_file_triplets.lo @@ -196,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -279,11 +287,12 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la +@MONOLITHIC_FALSE@libstrongswan_eap_sim_file_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la libstrongswan_eap_sim_file_la_SOURCES = \ eap_sim_file_plugin.h eap_sim_file_plugin.c \ eap_sim_file_card.h eap_sim_file_card.c \ diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c index 5397c418e..bd47e5085 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c @@ -35,7 +35,7 @@ struct private_eap_sim_file_card_t { eap_sim_file_triplets_t *triplets; }; -METHOD(sim_card_t, get_triplet, bool, +METHOD(simaka_card_t, get_triplet, bool, private_eap_sim_file_card_t *this, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { @@ -66,7 +66,7 @@ METHOD(sim_card_t, get_triplet, bool, return FALSE; } -METHOD(sim_card_t, get_quintuplet, status_t, +METHOD(simaka_card_t, get_quintuplet, status_t, private_eap_sim_file_card_t *this, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h index 1a5470968..45b0e51db 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.h @@ -23,7 +23,7 @@ #include "eap_sim_file_triplets.h" -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_card.h> typedef struct eap_sim_file_card_t eap_sim_file_card_t; @@ -33,9 +33,9 @@ typedef struct eap_sim_file_card_t eap_sim_file_card_t; struct eap_sim_file_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_sim_file_card_t. diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c index 0ab5a1848..eae76729c 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c @@ -56,14 +56,70 @@ METHOD(plugin_t, get_name, char*, return "eap-sim-file"; } -METHOD(plugin_t, destroy, void, - private_eap_sim_file_t *this) +/** + * Load triplet file + */ +static bool load_triplets(private_eap_sim_file_t *this, + plugin_feature_t *feature, bool reg, void *data) { - charon->sim->remove_card(charon->sim, &this->card->card); - charon->sim->remove_provider(charon->sim, &this->provider->provider); + if (reg) + { + this->triplets = eap_sim_file_triplets_create(TRIPLET_FILE); + if (!this->triplets) + { + return FALSE; + } + this->provider = eap_sim_file_provider_create(this->triplets); + this->card = eap_sim_file_card_create(this->triplets); + return TRUE; + } this->card->destroy(this->card); this->provider->destroy(this->provider); this->triplets->destroy(this->triplets); + this->card = NULL; + this->provider = NULL; + this->triplets = NULL; + return TRUE; +} + +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_sim_file_t *this) +{ + return &this->card->card; +} + +/** + * Callback providing our provider to register + */ +static simaka_provider_t* get_provider(private_eap_sim_file_t *this) +{ + return &this->provider->provider; +} + +METHOD(plugin_t, get_features, int, + private_eap_sim_file_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((void*)load_triplets, NULL), + PLUGIN_PROVIDE(CUSTOM, "eap-sim-file-triplets"), + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "sim-card"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-sim-file-triplets"), + PLUGIN_CALLBACK(simaka_manager_register, get_provider), + PLUGIN_PROVIDE(CUSTOM, "sim-provider"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-sim-file-triplets"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_eap_sim_file_t *this) +{ free(this); } @@ -78,25 +134,12 @@ plugin_t *eap_sim_file_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .triplets = eap_sim_file_triplets_create(TRIPLET_FILE), ); - this->provider = eap_sim_file_provider_create(this->triplets); - if (!this->provider) - { - this->triplets->destroy(this->triplets); - free(this); - return NULL; - } - this->card = eap_sim_file_card_create(this->triplets); - - charon->sim->add_card(charon->sim, &this->card->card); - charon->sim->add_provider(charon->sim, &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c index 38b651404..4ca1eb93f 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c @@ -35,7 +35,7 @@ struct private_eap_sim_file_provider_t { eap_sim_file_triplets_t *triplets; }; -METHOD(sim_provider_t, get_triplet, bool, +METHOD(simaka_provider_t, get_triplet, bool, private_eap_sim_file_provider_t *this, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h index 10fda282a..577345dbf 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.h @@ -23,6 +23,8 @@ #include "eap_sim_file_triplets.h" +#include <simaka_provider.h> + typedef struct eap_sim_file_provider_t eap_sim_file_provider_t; /** @@ -31,9 +33,9 @@ typedef struct eap_sim_file_provider_t eap_sim_file_provider_t; struct eap_sim_file_provider_t { /** - * Implements sim_provider_t interface. + * Implements simaka_provider_t interface. */ - sim_provider_t provider; + simaka_provider_t provider; /** * Destroy a eap_sim_file_provider_t. diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c index c693923fe..de3b69382 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c @@ -21,6 +21,7 @@ #include <daemon.h> #include <utils/linked_list.h> #include <threading/mutex.h> +#include <simaka_manager.h> typedef struct private_eap_sim_file_triplets_t private_eap_sim_file_triplets_t; @@ -149,7 +150,7 @@ static void parse_token(char *to, char *from, size_t len) /** * Read the triplets from the file */ -static void read_triplets(private_eap_sim_file_triplets_t *this, char *path) +static bool read_triplets(private_eap_sim_file_triplets_t *this, char *path) { char line[512]; FILE *file; @@ -160,7 +161,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path) { DBG1(DBG_CFG, "opening triplet file %s failed: %s", path, strerror(errno)); - return; + return FALSE; } /* read line by line */ @@ -226,6 +227,7 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path) DBG1(DBG_CFG, "read %d triplets from %s", this->triplets->get_count(this->triplets), path); + return TRUE; } METHOD(eap_sim_file_triplets_t, destroy, void, @@ -251,8 +253,12 @@ eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file) .triplets = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); - read_triplets(this, file); + if (!read_triplets(this, file)) + { + destroy(this); + return NULL; + } return &this->public; } diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h index 8f8130810..c8e9e0359 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.h @@ -21,7 +21,7 @@ #ifndef EAP_SIM_FILE_TRIPLETS_H_ #define EAP_SIM_FILE_TRIPLETS_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <utils/enumerator.h> typedef struct eap_sim_file_triplets_t eap_sim_file_triplets_t; diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am index 2d75fe3ad..fae6fccfc 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am @@ -1,18 +1,19 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic ${pcsclite_CFLAGS} +libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} + if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la else plugin_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la +libstrongswan_eap_sim_pcsc_la_LIBADD += $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_sim_pcsc_la_SOURCES = \ eap_sim_pcsc_plugin.h eap_sim_pcsc_plugin.c \ eap_sim_pcsc_card.h eap_sim_pcsc_card.c - -libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version -libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in index a8249a7ac..5c05b2bf1 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in @@ -34,6 +34,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@MONOLITHIC_FALSE@am__append_1 = $(top_builddir)/src/libsimaka/libsimaka.la subdir = src/libcharon/plugins/eap_sim_pcsc DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -75,7 +76,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = -libstrongswan_eap_sim_pcsc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +libstrongswan_eap_sim_pcsc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__append_1) am_libstrongswan_eap_sim_pcsc_la_OBJECTS = eap_sim_pcsc_plugin.lo \ eap_sim_pcsc_card.lo libstrongswan_eap_sim_pcsc_la_OBJECTS = \ @@ -196,6 +198,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +209,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +226,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +276,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -279,17 +288,18 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic ${pcsclite_CFLAGS} +libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} \ + $(am__append_1) @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la libstrongswan_eap_sim_pcsc_la_SOURCES = \ eap_sim_pcsc_plugin.h eap_sim_pcsc_plugin.c \ eap_sim_pcsc_card.h eap_sim_pcsc_card.c -libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version -libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} all: all-am .SUFFIXES: diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c index d0a2718f3..c3f0f24b3 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c @@ -87,7 +87,7 @@ static bool decode_imsi_ef(unsigned char *input, int input_len, char *output) return TRUE; } -METHOD(sim_card_t, get_triplet, bool, +METHOD(simaka_card_t, get_triplet, bool, private_eap_sim_pcsc_card_t *this, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { @@ -207,7 +207,8 @@ METHOD(sim_card_t, get_triplet, bool, if (dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) { - DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, dwRecvLength); + DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, + (u_int)dwRecvLength); continue; } @@ -223,7 +224,8 @@ METHOD(sim_card_t, get_triplet, bool, if (dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) { - DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, dwRecvLength); + DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, + (u_int)dwRecvLength); continue; } @@ -239,7 +241,8 @@ METHOD(sim_card_t, get_triplet, bool, if (dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) { - DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength); + DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, + (u_int)dwRecvLength); continue; } @@ -255,14 +258,15 @@ METHOD(sim_card_t, get_triplet, bool, if (dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS) { - DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength); + DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, + (u_int)dwRecvLength); continue; } if (!decode_imsi_ef(pbRecvBuffer, dwRecvLength-APDU_STATUS_LEN, imsi)) { DBG1(DBG_IKE, "Couldn't decode IMSI EF: %b", - pbRecvBuffer, dwRecvLength); + pbRecvBuffer, (u_int)dwRecvLength); continue; } @@ -288,7 +292,7 @@ METHOD(sim_card_t, get_triplet, bool, pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) { DBG1(DBG_IKE, "Run GSM Algorithm failed: %b", - pbRecvBuffer, dwRecvLength); + pbRecvBuffer, (u_int)dwRecvLength); continue; } @@ -305,7 +309,8 @@ METHOD(sim_card_t, get_triplet, bool, if (dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS) { - DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, dwRecvLength); + DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, + (u_int)dwRecvLength); continue; } @@ -320,7 +325,7 @@ METHOD(sim_card_t, get_triplet, bool, else { DBG1(DBG_IKE, "Get Response incorrect length: %b", - pbRecvBuffer, dwRecvLength); + pbRecvBuffer, (u_int)dwRecvLength); continue; } @@ -351,7 +356,7 @@ METHOD(sim_card_t, get_triplet, bool, return found; } -METHOD(sim_card_t, get_quintuplet, status_t, +METHOD(simaka_card_t, get_quintuplet, status_t, private_eap_sim_pcsc_card_t *this, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h index e7659656b..6b69f76ec 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h @@ -20,7 +20,7 @@ #ifndef EAP_SIM_PCSC_CARD_H_ #define EAP_SIM_PCSC_CARD_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_card.h> typedef struct eap_sim_pcsc_card_t eap_sim_pcsc_card_t; @@ -30,9 +30,9 @@ typedef struct eap_sim_pcsc_card_t eap_sim_pcsc_card_t; struct eap_sim_pcsc_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_sim_pcsc_card_t. diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c index 44096455e..898e85345 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c @@ -41,10 +41,29 @@ METHOD(plugin_t, get_name, char*, return "eap-sim-pcsc"; } +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_sim_pcsc_plugin_t *this) +{ + return &this->card->card; +} + +METHOD(plugin_t, get_features, int, + private_eap_sim_pcsc_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "sim-card"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_eap_sim_pcsc_plugin_t *this) { - charon->sim->remove_card(charon->sim, &this->card->card); this->card->destroy(this->card); free(this); } @@ -60,13 +79,12 @@ plugin_t *eap_sim_pcsc_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, .card = eap_sim_pcsc_card_create(), ); - charon->sim->add_card(charon->sim, &this->card->card); return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am index a158d6dbe..a8e03f650 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am @@ -1,6 +1,6 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic @@ -8,6 +8,7 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la else plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la +libstrongswan_eap_simaka_pseudonym_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_simaka_pseudonym_la_SOURCES = \ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index 98e80bc71..0d7c32c14 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -74,7 +74,8 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_simaka_pseudonym_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_pseudonym_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la am_libstrongswan_eap_simaka_pseudonym_la_OBJECTS = \ eap_simaka_pseudonym_plugin.lo eap_simaka_pseudonym_card.lo \ eap_simaka_pseudonym_provider.lo @@ -197,6 +198,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -205,6 +209,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -221,11 +226,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -269,6 +276,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -280,11 +288,12 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_pseudonym_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la libstrongswan_eap_simaka_pseudonym_la_SOURCES = \ eap_simaka_pseudonym_plugin.h eap_simaka_pseudonym_plugin.c \ eap_simaka_pseudonym_card.h eap_simaka_pseudonym_card.c \ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c index 9b0f1bc71..5f78c967a 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.c @@ -57,11 +57,8 @@ static bool equals(identification_t *key1, identification_t *key2) return key1->equals(key1, key2); } -/** - * Implementation of sim_card_t.get_pseudonym - */ -static identification_t *get_pseudonym(private_eap_simaka_pseudonym_card_t *this, - identification_t *id) +METHOD(simaka_card_t, get_pseudonym, identification_t*, + private_eap_simaka_pseudonym_card_t *this, identification_t *id) { identification_t *pseudonym; @@ -73,11 +70,9 @@ static identification_t *get_pseudonym(private_eap_simaka_pseudonym_card_t *this return NULL; } -/** - * Implementation of sim_card_t.set_pseudonym - */ -static void set_pseudonym(private_eap_simaka_pseudonym_card_t *this, - identification_t *id, identification_t *pseudonym) +METHOD(simaka_card_t, set_pseudonym, void, + private_eap_simaka_pseudonym_card_t *this, identification_t *id, + identification_t *pseudonym) { identification_t *permanent; @@ -92,18 +87,16 @@ static void set_pseudonym(private_eap_simaka_pseudonym_card_t *this, DESTROY_IF(pseudonym); } -/** - * Implementation of sim_card_t.get_quintuplet - */ -static status_t get_quintuplet() +METHOD(simaka_card_t, get_quintuplet, status_t, + private_eap_simaka_pseudonym_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) { return NOT_SUPPORTED; } -/** - * Implementation of eap_simaka_pseudonym_card_t.destroy. - */ -static void destroy(private_eap_simaka_pseudonym_card_t *this) +METHOD(eap_simaka_pseudonym_card_t, destroy, void, + private_eap_simaka_pseudonym_card_t *this) { enumerator_t *enumerator; identification_t *id; @@ -135,19 +128,22 @@ eap_simaka_pseudonym_card_t *eap_simaka_pseudonym_card_create() { private_eap_simaka_pseudonym_card_t *this; - this = malloc_thing(private_eap_simaka_pseudonym_card_t); - - this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false; - this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet; - this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))get_pseudonym; - this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))set_pseudonym; - this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop; - this->public.destroy = (void(*)(eap_simaka_pseudonym_card_t*))destroy; - - this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0); - this->permanent = hashtable_create((void*)hash, (void*)equals, 0); + INIT(this, + .public = { + .card = { + .get_triplet = (void*)return_false, + .get_quintuplet = _get_quintuplet, + .resync = (void*)return_false, + .get_pseudonym = _get_pseudonym, + .set_pseudonym = _set_pseudonym, + .get_reauth = (void*)return_null, + .set_reauth = (void*)nop, + }, + .destroy = _destroy, + }, + .pseudonym = hashtable_create((void*)hash, (void*)equals, 0), + .permanent = hashtable_create((void*)hash, (void*)equals, 0), + ); return &this->public; } diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h index 1b5940fdc..6c73a8cb9 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_card.h @@ -21,7 +21,7 @@ #ifndef EAP_SIMAKA_PSEUDONYM_CARD_H_ #define EAP_SIMAKA_PSEUDONYM_CARD_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_card.h> typedef struct eap_simaka_pseudonym_card_t eap_simaka_pseudonym_card_t; @@ -31,9 +31,9 @@ typedef struct eap_simaka_pseudonym_card_t eap_simaka_pseudonym_card_t; struct eap_simaka_pseudonym_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_simaka_pseudonym_card_t. diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c index 06631b1c5..e2cc0e84f 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c @@ -48,13 +48,60 @@ METHOD(plugin_t, get_name, char*, return "eap-simaka-pseudonym"; } +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_simaka_pseudonym_t *this) +{ + if (!this->card) + { + this->card = eap_simaka_pseudonym_card_create(); + } + return &this->card->card; +} + +/** + * Callback providing our provider to register + */ +static simaka_provider_t* get_provider(private_eap_simaka_pseudonym_t *this) +{ + if (!this->provider) + { + this->provider = eap_simaka_pseudonym_provider_create(); + if (!this->provider) + { + return NULL; + } + } + return &this->provider->provider; +} + +METHOD(plugin_t, get_features, int, + private_eap_simaka_pseudonym_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "aka-card"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_PROVIDE(CUSTOM, "sim-card"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_CALLBACK(simaka_manager_register, get_provider), + PLUGIN_PROVIDE(CUSTOM, "aka-provider"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_PROVIDE(CUSTOM, "sim-provider"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_eap_simaka_pseudonym_t *this) { - charon->sim->remove_card(charon->sim, &this->card->card); - charon->sim->remove_provider(charon->sim, &this->provider->provider); - this->card->destroy(this->card); - this->provider->destroy(this->provider); + DESTROY_IF(this->card); + DESTROY_IF(this->provider); free(this); } @@ -69,23 +116,12 @@ plugin_t *eap_simaka_pseudonym_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .provider = eap_simaka_pseudonym_provider_create(), ); - if (!this->provider) - { - free(this); - return NULL; - } - this->card = eap_simaka_pseudonym_card_create(); - - charon->sim->add_card(charon->sim, &this->card->card); - charon->sim->add_provider(charon->sim, &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c index 0613b8807..49c3ad328 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.c @@ -61,11 +61,8 @@ static bool equals(identification_t *key1, identification_t *key2) return key1->equals(key1, key2); } -/** - * Implementation of sim_provider_t.is_pseudonym - */ -static identification_t* is_pseudonym( - private_eap_simaka_pseudonym_provider_t *this, identification_t *id) +METHOD(simaka_provider_t, is_pseudonym, identification_t*, + private_eap_simaka_pseudonym_provider_t *this, identification_t *id) { identification_t *permanent; @@ -91,11 +88,8 @@ static identification_t *gen_identity( return identification_create_from_string(hex); } -/** - * Implementation of sim_provider_t.get_pseudonym - */ -static identification_t* gen_pseudonym( - private_eap_simaka_pseudonym_provider_t *this, identification_t *id) +METHOD(simaka_provider_t, gen_pseudonym, identification_t*, + private_eap_simaka_pseudonym_provider_t *this, identification_t *id) { identification_t *pseudonym, *permanent; @@ -121,10 +115,8 @@ static identification_t* gen_pseudonym( return pseudonym->clone(pseudonym); } -/** - * Implementation of eap_simaka_pseudonym_provider_t.destroy. - */ -static void destroy(private_eap_simaka_pseudonym_provider_t *this) +METHOD(eap_simaka_pseudonym_provider_t, destroy, void, + private_eap_simaka_pseudonym_provider_t *this) { enumerator_t *enumerator; identification_t *id; @@ -157,18 +149,21 @@ eap_simaka_pseudonym_provider_t *eap_simaka_pseudonym_provider_create() { private_eap_simaka_pseudonym_provider_t *this; - this = malloc_thing(private_eap_simaka_pseudonym_provider_t); - - this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false; - this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false; - this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))is_pseudonym; - this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))gen_pseudonym; - this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null; - this->public.destroy = (void(*)(eap_simaka_pseudonym_provider_t*))destroy; - - this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + INIT(this, + .public = { + .provider = { + .get_triplet = (void*)return_false, + .get_quintuplet = (void*)return_false, + .resync = (void*)return_false, + .is_pseudonym = _is_pseudonym, + .gen_pseudonym = _gen_pseudonym, + .is_reauth = (void*)return_null, + .gen_reauth = (void*)return_null, + }, + .destroy = _destroy, + }, + .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), + ); if (!this->rng) { free(this); diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h index 5d8e6d221..2dea516c3 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_provider.h @@ -21,7 +21,7 @@ #ifndef EAP_SIMAKA_PSEDUONYM_PROVIDER_H_ #define EAP_SIMAKA_PSEDUONYM_PROVIDER_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_provider.h> typedef struct eap_simaka_pseudonym_provider_t eap_simaka_pseudonym_provider_t; @@ -31,9 +31,9 @@ typedef struct eap_simaka_pseudonym_provider_t eap_simaka_pseudonym_provider_t; struct eap_simaka_pseudonym_provider_t { /** - * Implements sim_provider_t interface. + * Implements simaka_provider_t interface. */ - sim_provider_t provider; + simaka_provider_t provider; /** * Destroy a eap_simaka_pseudonym_provider_t. diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am index fbcd544d3..0b35c7521 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am @@ -1,6 +1,6 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic @@ -8,6 +8,7 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la else plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la +libstrongswan_eap_simaka_reauth_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_simaka_reauth_la_SOURCES = \ diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index 56bc188b0..6177f3b3a 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -74,7 +74,8 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_simaka_reauth_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_reauth_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la am_libstrongswan_eap_simaka_reauth_la_OBJECTS = \ eap_simaka_reauth_plugin.lo eap_simaka_reauth_card.lo \ eap_simaka_reauth_provider.lo @@ -196,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -279,11 +287,12 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_reauth_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la libstrongswan_eap_simaka_reauth_la_SOURCES = \ eap_simaka_reauth_plugin.h eap_simaka_reauth_plugin.c \ eap_simaka_reauth_card.h eap_simaka_reauth_card.c \ diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c index 14d0416d9..870d72781 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.c @@ -66,12 +66,9 @@ static bool equals(identification_t *key1, identification_t *key2) return key1->equals(key1, key2); } -/** - * Implementation of sim_card_t.get_reauth - */ -static identification_t *get_reauth(private_eap_simaka_reauth_card_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) +METHOD(simaka_card_t, get_reauth, identification_t*, + private_eap_simaka_reauth_card_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1], u_int16_t *counter) { reauth_data_t *data; identification_t *reauth; @@ -90,12 +87,9 @@ static identification_t *get_reauth(private_eap_simaka_reauth_card_t *this, return reauth; } -/** - * Implementation of sim_card_t.set_reauth - */ -static void set_reauth(private_eap_simaka_reauth_card_t *this, - identification_t *id, identification_t* next, - char mk[HASH_SIZE_SHA1], u_int16_t counter) +METHOD(simaka_card_t, set_reauth, void, + private_eap_simaka_reauth_card_t *this, identification_t *id, + identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter) { reauth_data_t *data; @@ -115,18 +109,16 @@ static void set_reauth(private_eap_simaka_reauth_card_t *this, memcpy(data->mk, mk, HASH_SIZE_SHA1); } -/** - * Implementation of sim_card_t.get_quintuplet - */ -static status_t get_quintuplet() +METHOD(simaka_card_t, get_quintuplet, status_t, + private_eap_simaka_reauth_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) { return NOT_SUPPORTED; } -/** - * Implementation of eap_simaka_reauth_card_t.destroy. - */ -static void destroy(private_eap_simaka_reauth_card_t *this) +METHOD(eap_simaka_reauth_card_t, destroy, void, + private_eap_simaka_reauth_card_t *this) { enumerator_t *enumerator; reauth_data_t *data; @@ -152,18 +144,21 @@ eap_simaka_reauth_card_t *eap_simaka_reauth_card_create() { private_eap_simaka_reauth_card_t *this; - this = malloc_thing(private_eap_simaka_reauth_card_t); - - this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_null; - this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet; - this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))return_null; - this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop; - this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))get_reauth; - this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))set_reauth; - this->public.destroy = (void(*)(eap_simaka_reauth_card_t*))destroy; - - this->reauth = hashtable_create((void*)hash, (void*)equals, 0); + INIT(this, + .public = { + .card = { + .get_triplet = (void*)return_null, + .get_quintuplet = _get_quintuplet, + .resync = (void*)return_false, + .get_pseudonym = (void*)return_null, + .set_pseudonym = (void*)nop, + .get_reauth = _get_reauth, + .set_reauth = _set_reauth, + }, + .destroy = _destroy, + }, + .reauth = hashtable_create((void*)hash, (void*)equals, 0), + ); return &this->public; } diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h index f24dc8a15..683de7559 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_card.h @@ -21,7 +21,7 @@ #ifndef EAP_SIMAKA_REAUTH_CARD_H_ #define EAP_SIMAKA_REAUTH_CARD_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_provider.h> typedef struct eap_simaka_reauth_card_t eap_simaka_reauth_card_t; @@ -31,9 +31,9 @@ typedef struct eap_simaka_reauth_card_t eap_simaka_reauth_card_t; struct eap_simaka_reauth_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_simaka_reauth_card_t. diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c index 343e4eefb..ab3ab2f4d 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c @@ -48,13 +48,60 @@ METHOD(plugin_t, get_name, char*, return "eap-simaka-reauth"; } +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_simaka_reauth_t *this) +{ + if (!this->card) + { + this->card = eap_simaka_reauth_card_create(); + } + return &this->card->card; +} + +/** + * Callback providing our provider to register + */ +static simaka_provider_t* get_provider(private_eap_simaka_reauth_t *this) +{ + if (!this->provider) + { + this->provider = eap_simaka_reauth_provider_create(); + if (!this->provider) + { + return NULL; + } + } + return &this->provider->provider; +} + +METHOD(plugin_t, get_features, int, + private_eap_simaka_reauth_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "aka-card"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_PROVIDE(CUSTOM, "sim-card"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_CALLBACK(simaka_manager_register, get_provider), + PLUGIN_PROVIDE(CUSTOM, "aka-provider"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_PROVIDE(CUSTOM, "sim-provider"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_eap_simaka_reauth_t *this) { - charon->sim->remove_card(charon->sim, &this->card->card); - charon->sim->remove_provider(charon->sim, &this->provider->provider); - this->card->destroy(this->card); - this->provider->destroy(this->provider); + DESTROY_IF(this->card); + DESTROY_IF(this->provider); free(this); } @@ -69,23 +116,12 @@ plugin_t *eap_simaka_reauth_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .provider = eap_simaka_reauth_provider_create(), ); - if (!this->provider) - { - free(this); - return NULL; - } - this->card = eap_simaka_reauth_card_create(); - - charon->sim->add_card(charon->sim, &this->card->card); - charon->sim->add_provider(charon->sim, &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c index f962b2d84..ba1a32778 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.c @@ -87,12 +87,9 @@ static identification_t *gen_identity(private_eap_simaka_reauth_provider_t *this return identification_create_from_string(hex); } -/** - * Implementation of sim_provider_t.is_reauth - */ -static identification_t *is_reauth(private_eap_simaka_reauth_provider_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) +METHOD(simaka_provider_t, is_reauth, identification_t*, + private_eap_simaka_reauth_provider_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1], u_int16_t *counter) { identification_t *permanent; reauth_data_t *data; @@ -114,11 +111,9 @@ static identification_t *is_reauth(private_eap_simaka_reauth_provider_t *this, return permanent->clone(permanent); } -/** - * Implementation of sim_provider_t.gen_reauth - */ -static identification_t *gen_reauth(private_eap_simaka_reauth_provider_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1]) +METHOD(simaka_provider_t, gen_reauth, identification_t*, + private_eap_simaka_reauth_provider_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1]) { reauth_data_t *data; identification_t *permanent; @@ -136,9 +131,9 @@ static identification_t *gen_reauth(private_eap_simaka_reauth_provider_t *this, } else { /* generate new entry */ - data = malloc_thing(reauth_data_t); - data->counter = 0; - data->id = gen_identity(this); + INIT(data, + .id = gen_identity(this), + ); id = id->clone(id); this->reauth->put(this->reauth, id, data); this->permanent->put(this->permanent, data->id, id); @@ -148,10 +143,8 @@ static identification_t *gen_reauth(private_eap_simaka_reauth_provider_t *this, return data->id->clone(data->id); } -/** - * Implementation of eap_simaka_reauth_provider_t.destroy. - */ -static void destroy(private_eap_simaka_reauth_provider_t *this) +METHOD(eap_simaka_reauth_provider_t, destroy, void, + private_eap_simaka_reauth_provider_t *this) { enumerator_t *enumerator; identification_t *id; @@ -184,18 +177,23 @@ static void destroy(private_eap_simaka_reauth_provider_t *this) */ eap_simaka_reauth_provider_t *eap_simaka_reauth_provider_create() { - private_eap_simaka_reauth_provider_t *this = malloc_thing(private_eap_simaka_reauth_provider_t); - - this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))return_false; - this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false; - this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))is_reauth; - this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))gen_reauth; - this->public.destroy = (void(*)(eap_simaka_reauth_provider_t*))destroy; - - this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + private_eap_simaka_reauth_provider_t *this; + + INIT(this, + .public = { + .provider = { + .get_triplet = (void*)return_false, + .get_quintuplet = (void*)return_false, + .resync = (void*)return_false, + .is_pseudonym = (void*)return_null, + .gen_pseudonym = (void*)return_null, + .is_reauth = _is_reauth, + .gen_reauth = _gen_reauth, + }, + .destroy = _destroy, + }, + .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), + ); if (!this->rng) { free(this); diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h index 7ae151a27..bc6376d53 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_provider.h @@ -21,7 +21,7 @@ #ifndef EAP_SIMAKA_REAUTH_PROVIDER_H_ #define EAP_SIMAKA_REAUTH_PROVIDER_H_ -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_provider.h> typedef struct eap_simaka_reauth_provider_t eap_simaka_reauth_provider_t; @@ -31,9 +31,9 @@ typedef struct eap_simaka_reauth_provider_t eap_simaka_reauth_provider_t; struct eap_simaka_reauth_provider_t { /** - * Implements sim_provider_t interface. + * Implements simaka_provider_t interface. */ - sim_provider_t provider; + simaka_provider_t provider; /** * Destroy a eap_simaka_reauth_provider_t. diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am index 73768be0e..c83267e67 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.am +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am @@ -1,6 +1,6 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" @@ -8,6 +8,7 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la else plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +libstrongswan_eap_simaka_sql_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la endif libstrongswan_eap_simaka_sql_la_SOURCES = \ diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in index 93c7aed03..3639e24e8 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -74,7 +74,8 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_eap_simaka_sql_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_sql_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libsimaka/libsimaka.la am_libstrongswan_eap_simaka_sql_la_OBJECTS = eap_simaka_sql_plugin.lo \ eap_simaka_sql_card.lo eap_simaka_sql_provider.lo libstrongswan_eap_simaka_sql_la_OBJECTS = \ @@ -195,6 +196,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +207,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +224,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +274,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -278,11 +286,12 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libsimaka AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +@MONOLITHIC_FALSE@libstrongswan_eap_simaka_sql_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la libstrongswan_eap_simaka_sql_la_SOURCES = \ eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \ eap_simaka_sql_card.h eap_simaka_sql_card.c \ diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c index b7590405f..90627b52e 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c @@ -42,7 +42,7 @@ struct private_eap_simaka_sql_card_t { bool remove_used; }; -METHOD(sim_card_t, get_triplet, bool, +METHOD(simaka_card_t, get_triplet, bool, private_eap_simaka_sql_card_t *this, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { @@ -90,7 +90,7 @@ METHOD(sim_card_t, get_triplet, bool, return found; } -METHOD(sim_card_t, get_quintuplet, status_t, +METHOD(simaka_card_t, get_quintuplet, status_t, private_eap_simaka_sql_card_t *this, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h index 46b7de25e..760755a56 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h @@ -22,7 +22,7 @@ #define EAP_SIMAKA_SQL_CARD_H_ #include <database/database.h> -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_manager.h> typedef struct eap_simaka_sql_card_t eap_simaka_sql_card_t; @@ -32,9 +32,9 @@ typedef struct eap_simaka_sql_card_t eap_simaka_sql_card_t; struct eap_simaka_sql_card_t { /** - * Implements sim_card_t interface + * Implements simaka_card_t interface */ - sim_card_t card; + simaka_card_t card; /** * Destroy a eap_simaka_sql_card_t. diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c index 5a528153d..6e590fae7 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c @@ -53,14 +53,93 @@ METHOD(plugin_t, get_name, char*, return "eap-simaka-sql"; } -METHOD(plugin_t, destroy, void, - private_eap_simaka_sql_t *this) +/** + * Load database + */ +static bool load_db(private_eap_simaka_sql_t *this, + plugin_feature_t *feature, bool reg, void *data) { - charon->sim->remove_card(charon->sim, &this->card->card); - charon->sim->remove_provider(charon->sim, &this->provider->provider); + if (reg) + { + bool remove_used; + char *uri; + + uri = lib->settings->get_str(lib->settings, + "charon.plugins.eap-simaka-sql.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "eap-simaka-sql database URI missing"); + return FALSE; + } + this->db = lib->db->create(lib->db, uri); + if (!this->db) + { + DBG1(DBG_CFG, "opening eap-simaka-sql database failed"); + return FALSE; + } + remove_used = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-simaka-sql.remove_used", FALSE); + + this->provider = eap_simaka_sql_provider_create(this->db, remove_used); + this->card = eap_simaka_sql_card_create(this->db, remove_used); + return TRUE; + } this->card->destroy(this->card); this->provider->destroy(this->provider); this->db->destroy(this->db); + this->card = NULL; + this->provider = NULL; + this->db = NULL; + return TRUE; +} + +/** + * Callback providing our card to register + */ +static simaka_card_t* get_card(private_eap_simaka_sql_t *this) +{ + return &this->card->card; +} + +/** + * Callback providing our provider to register + */ +static simaka_provider_t* get_provider(private_eap_simaka_sql_t *this) +{ + return &this->provider->provider; +} + +METHOD(plugin_t, get_features, int, + private_eap_simaka_sql_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((void*)load_db, NULL), + PLUGIN_PROVIDE(CUSTOM, "eap-simaka-sql-db"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + PLUGIN_SDEPEND(DATABASE, DB_SQLITE), + PLUGIN_SDEPEND(DATABASE, DB_MYSQL), + PLUGIN_CALLBACK(simaka_manager_register, get_card), + PLUGIN_PROVIDE(CUSTOM, "aka-card"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-simaka-sql-db"), + PLUGIN_PROVIDE(CUSTOM, "sim-card"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-simaka-sql-db"), + PLUGIN_CALLBACK(simaka_manager_register, get_provider), + PLUGIN_PROVIDE(CUSTOM, "aka-provider"), + PLUGIN_DEPENDS(CUSTOM, "aka-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-simaka-sql-db"), + PLUGIN_PROVIDE(CUSTOM, "sim-provider"), + PLUGIN_DEPENDS(CUSTOM, "sim-manager"), + PLUGIN_DEPENDS(CUSTOM, "eap-simaka-sql-db"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_eap_simaka_sql_t *this) +{ free(this); } @@ -70,41 +149,16 @@ METHOD(plugin_t, destroy, void, plugin_t *eap_simaka_sql_plugin_create() { private_eap_simaka_sql_t *this; - database_t *db; - bool remove_used; - char *uri; - - uri = lib->settings->get_str(lib->settings, - "charon.plugins.eap-simaka-sql.database", NULL); - if (!uri) - { - DBG1(DBG_CFG, "eap-simaka-sql database URI missing"); - return NULL; - } - db = lib->db->create(lib->db, uri); - if (!db) - { - DBG1(DBG_CFG, "opening eap-simaka-sql database failed"); - return NULL; - } - remove_used = lib->settings->get_bool(lib->settings, - "charon.plugins.eap-simaka-sql.remove_used", FALSE); INIT(this, .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, - .db = db, - .provider = eap_simaka_sql_provider_create(db, remove_used), - .card = eap_simaka_sql_card_create(db, remove_used), ); - charon->sim->add_card(charon->sim, &this->card->card); - charon->sim->add_provider(charon->sim, &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c index 73cccf549..21a19655f 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c @@ -42,7 +42,7 @@ struct private_eap_simaka_sql_provider_t { bool remove_used; }; -METHOD(sim_provider_t, get_triplet, bool, +METHOD(simaka_provider_t, get_triplet, bool, private_eap_simaka_sql_provider_t *this, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { @@ -53,7 +53,7 @@ METHOD(sim_provider_t, get_triplet, bool, snprintf(buf, sizeof(buf), "%Y", id); query = this->db->query(this->db, - "select rand, sres, kc from triplets where id = ? order by use", + "select rand, sres, kc from triplets where id = ? order by used", DB_TEXT, buf, DB_BLOB, DB_BLOB, DB_BLOB); if (query) { @@ -82,7 +82,7 @@ METHOD(sim_provider_t, get_triplet, bool, else { this->db->execute(this->db, NULL, - "update triplets set use = ? where id = ? and rand = ?", + "update triplets set used = ? where id = ? and rand = ?", DB_UINT, time(NULL), DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); } @@ -90,7 +90,7 @@ METHOD(sim_provider_t, get_triplet, bool, return found; } -METHOD(sim_provider_t, get_quintuplet, bool, +METHOD(simaka_provider_t, get_quintuplet, bool, private_eap_simaka_sql_provider_t *this, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]) @@ -102,7 +102,7 @@ METHOD(sim_provider_t, get_quintuplet, bool, snprintf(buf, sizeof(buf), "%Y", id); query = this->db->query(this->db, "select rand, res, ck, ik, autn " - "from quintuplets where id = ? order by use", DB_TEXT, buf, + "from quintuplets where id = ? order by used", DB_TEXT, buf, DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB); if (query) { @@ -137,7 +137,7 @@ METHOD(sim_provider_t, get_quintuplet, bool, else { this->db->execute(this->db, NULL, - "update quintuplets set use = ? where id = ? and rand = ?", + "update quintuplets set used = ? where id = ? and rand = ?", DB_UINT, time(NULL), DB_TEXT, buf, DB_BLOB, chunk_create(rand, AKA_RAND_LEN)); } diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h index ecb0c8cb0..88a8b1f24 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h @@ -22,7 +22,7 @@ #define EAP_SIMAKA_SQL_PROVIDER_H_ #include <database/database.h> -#include <sa/authenticators/eap/sim_manager.h> +#include <simaka_provider.h> typedef struct eap_simaka_sql_provider_t eap_simaka_sql_provider_t; @@ -32,9 +32,9 @@ typedef struct eap_simaka_sql_provider_t eap_simaka_sql_provider_t; struct eap_simaka_sql_provider_t { /** - * Implements sim_provider_t interface + * Implements simaka_provider_t interface */ - sim_provider_t provider; + simaka_provider_t provider; /** * Destroy a eap_simaka_sql_provider_t. diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in index c58bced06..67e2c0cb0 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.in +++ b/src/libcharon/plugins/eap_tls/Makefile.in @@ -194,6 +194,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +205,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +222,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +272,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c index 39e1a60d9..dc0289ba2 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls.c +++ b/src/libcharon/plugins/eap_tls/eap_tls.c @@ -39,7 +39,7 @@ struct private_eap_tls_t { }; /** Maximum number of EAP-TLS messages/fragments allowed */ -#define MAX_MESSAGE_COUNT 32 +#define MAX_MESSAGE_COUNT 32 /** Default size of a EAP-TLS fragment */ #define MAX_FRAGMENT_LEN 1024 @@ -148,8 +148,8 @@ static eap_tls_t *eap_tls_create(identification_t *server, max_msg_count = lib->settings->get_int(lib->settings, "charon.plugins.eap-tls.max_message_count", MAX_MESSAGE_COUNT); include_length = lib->settings->get_bool(lib->settings, - "charon.plugins.eap-tls.include_length", TRUE); - tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TLS, NULL); + "charon.plugins.eap-tls.include_length", TRUE); + tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TLS, NULL, NULL); this->tls_eap = tls_eap_create(EAP_TLS, tls, frag_size, max_msg_count, include_length); if (!this->tls_eap) diff --git a/src/libcharon/plugins/eap_tls/eap_tls_plugin.c b/src/libcharon/plugins/eap_tls/eap_tls_plugin.c index 7afb79819..5507d8e02 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls_plugin.c +++ b/src/libcharon/plugins/eap_tls/eap_tls_plugin.c @@ -25,13 +25,29 @@ METHOD(plugin_t, get_name, char*, return "eap-tls"; } +METHOD(plugin_t, get_features, int, + eap_tls_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_tls_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_TLS), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(eap_method_register, eap_tls_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_TLS), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(RNG, RNG_STRONG), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_tls_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_tls_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_tls_create_peer); free(this); } @@ -45,15 +61,10 @@ plugin_t *eap_tls_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_TLS, 0, EAP_SERVER, - (eap_constructor_t)eap_tls_create_server); - charon->eap->add_method(charon->eap, EAP_TLS, 0, EAP_PEER, - (eap_constructor_t)eap_tls_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_tnc/Makefile.am b/src/libcharon/plugins/eap_tnc/Makefile.am index 9c5a445c5..0e10f7d9c 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.am +++ b/src/libcharon/plugins/eap_tnc/Makefile.am @@ -1,6 +1,11 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @@ -8,7 +13,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-tnc.la else plugin_LTLIBRARIES = libstrongswan-eap-tnc.la -libstrongswan_eap_tnc_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libstrongswan_eap_tnc_la_LIBADD = \ + $(top_builddir)/src/libtls/libtls.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_eap_tnc_la_SOURCES = \ diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in index dfc052bf8..62278f835 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.in +++ b/src/libcharon/plugins/eap_tnc/Makefile.in @@ -75,7 +75,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) @MONOLITHIC_FALSE@libstrongswan_eap_tnc_la_DEPENDENCIES = \ -@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la am_libstrongswan_eap_tnc_la_OBJECTS = eap_tnc_plugin.lo eap_tnc.lo libstrongswan_eap_tnc_la_OBJECTS = \ $(am_libstrongswan_eap_tnc_la_OBJECTS) @@ -194,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -276,13 +284,21 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-tnc.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-tnc.la -@MONOLITHIC_FALSE@libstrongswan_eap_tnc_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@libstrongswan_eap_tnc_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + libstrongswan_eap_tnc_la_SOURCES = \ eap_tnc_plugin.h eap_tnc_plugin.c eap_tnc.h eap_tnc.c diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index ab3f87688..33a83ba18 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -15,9 +15,9 @@ #include "eap_tnc.h" +#include <tnc/tnc.h> +#include <tnc/tnccs/tnccs_manager.h> #include <tls_eap.h> - -#include <daemon.h> #include <debug.h> typedef struct private_eap_tnc_t private_eap_tnc_t; @@ -172,7 +172,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, free(this); return NULL; } - tnccs = charon->tnccs->create_instance(charon->tnccs, type, is_server); + tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server); this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size, max_msg_count, include_length); if (!this->tls_eap) diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c index 93847e636..813a75f48 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c @@ -24,13 +24,26 @@ METHOD(plugin_t, get_name, char*, return "eap-tnc"; } +METHOD(plugin_t, get_features, int, + eap_tnc_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_tnc_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_TNC), + PLUGIN_DEPENDS(EAP_SERVER, EAP_TTLS), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + PLUGIN_CALLBACK(eap_method_register, eap_tnc_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_TNC), + PLUGIN_DEPENDS(EAP_PEER, EAP_TTLS), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_tnc_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_tnc_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_tnc_create_peer); free(this); } @@ -44,16 +57,11 @@ plugin_t *eap_tnc_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_TNC, 0, EAP_SERVER, - (eap_constructor_t)eap_tnc_create_server); - charon->eap->add_method(charon->eap, EAP_TNC, 0, EAP_PEER, - (eap_constructor_t)eap_tnc_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am index 94ce5cc1e..8cc82cc2e 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.am +++ b/src/libcharon/plugins/eap_ttls/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libradius AM_CFLAGS = -rdynamic diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in index d0d5341e2..b41fbd719 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.in +++ b/src/libcharon/plugins/eap_ttls/Makefile.in @@ -197,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -205,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -221,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -269,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -280,7 +287,8 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libradius AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-ttls.la diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c index 7193bc9f0..ace62f6b9 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c @@ -156,7 +156,8 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, "charon.plugins.eap-ttls.max_message_count", MAX_MESSAGE_COUNT); include_length = lib->settings->get_bool(lib->settings, "charon.plugins.eap-ttls.include_length", TRUE); - tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TTLS, application); + tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TTLS, + application, NULL); this->tls_eap = tls_eap_create(EAP_TTLS, tls, frag_size, max_msg_count, include_length); if (!this->tls_eap) diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c index 0eb5e94be..0d531c437 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.c @@ -54,7 +54,7 @@ struct private_eap_ttls_avp_t { }; METHOD(eap_ttls_avp_t, build, void, - private_eap_ttls_avp_t *this, tls_writer_t *writer, chunk_t data) + private_eap_ttls_avp_t *this, bio_writer_t *writer, chunk_t data) { char zero_padding[] = { 0x00, 0x00, 0x00 }; chunk_t avp_padding; @@ -73,14 +73,14 @@ METHOD(eap_ttls_avp_t, build, void, } METHOD(eap_ttls_avp_t, process, status_t, - private_eap_ttls_avp_t* this, tls_reader_t *reader, chunk_t *data) + private_eap_ttls_avp_t* this, bio_reader_t *reader, chunk_t *data) { size_t len; chunk_t buf; if (this->process_header) { - tls_reader_t *header; + bio_reader_t *header; u_int32_t avp_code; u_int8_t avp_flags; u_int32_t avp_len; @@ -110,7 +110,7 @@ METHOD(eap_ttls_avp_t, process, status_t, } /* parse AVP header */ - header = tls_reader_create(this->input); + header = bio_reader_create(this->input); success = header->read_uint32(header, &avp_code) && header->read_uint8(header, &avp_flags) && header->read_uint24(header, &avp_len); diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.h b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.h index cad1d9c56..e56d92fc2 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_avp.h +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_avp.h @@ -25,8 +25,8 @@ typedef struct eap_ttls_avp_t eap_ttls_avp_t; #include <library.h> -#include <tls_reader.h> -#include <tls_writer.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> /** * EAP-TTLS Attribute-Value Pair (AVP) handler. @@ -43,7 +43,7 @@ struct eap_ttls_avp_t { * - FAILED if AVP processing failed * - NEED_MORE if another invocation of process/build needed */ - status_t (*process)(eap_ttls_avp_t *this, tls_reader_t *reader, + status_t (*process)(eap_ttls_avp_t *this, bio_reader_t *reader, chunk_t *data); /** @@ -52,7 +52,7 @@ struct eap_ttls_avp_t { * @param writer TLS data buffer to write to * @param data EAP Message to send */ - void (*build)(eap_ttls_avp_t *this, tls_writer_t *writer, chunk_t data); + void (*build)(eap_ttls_avp_t *this, bio_writer_t *writer, chunk_t data); /** * Destroy a eap_ttls_application_t. diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c index 931eb2e89..4b6897b1d 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c @@ -18,7 +18,7 @@ #include <debug.h> #include <daemon.h> - +#include <radius_message.h> #include <sa/authenticators/eap/eap_method.h> typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t; @@ -64,10 +64,8 @@ struct private_eap_ttls_peer_t { eap_ttls_avp_t *avp; }; -#define MAX_RADIUS_ATTRIBUTE_SIZE 253 - METHOD(tls_application_t, process, status_t, - private_eap_ttls_peer_t *this, tls_reader_t *reader) + private_eap_ttls_peer_t *this, bio_reader_t *reader) { chunk_t avp_data = chunk_empty; chunk_t eap_data = chunk_empty; @@ -229,7 +227,7 @@ METHOD(tls_application_t, process, status_t, } METHOD(tls_application_t, build, status_t, - private_eap_ttls_peer_t *this, tls_writer_t *writer) + private_eap_ttls_peer_t *this, bio_writer_t *writer) { chunk_t data; eap_code_t code; diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c index cbc3929bb..7ccbc9381 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c @@ -25,13 +25,31 @@ METHOD(plugin_t, get_name, char*, return "eap-ttls"; } +METHOD(plugin_t, get_features, int, + eap_ttls_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(eap_method_register, eap_ttls_create_server), + PLUGIN_PROVIDE(EAP_SERVER, EAP_TTLS), + PLUGIN_DEPENDS(EAP_SERVER, EAP_IDENTITY), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_CALLBACK(eap_method_register, eap_ttls_create_peer), + PLUGIN_PROVIDE(EAP_PEER, EAP_TTLS), + PLUGIN_DEPENDS(EAP_PEER, EAP_IDENTITY), + PLUGIN_DEPENDS(HASHER, HASH_MD5), + PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_DEPENDS(RNG, RNG_WEAK), + PLUGIN_DEPENDS(RNG, RNG_STRONG), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, eap_ttls_plugin_t *this) { - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_ttls_create_server); - charon->eap->remove_method(charon->eap, - (eap_constructor_t)eap_ttls_create_peer); free(this); } @@ -45,15 +63,10 @@ plugin_t *eap_ttls_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->eap->add_method(charon->eap, EAP_TTLS, 0, EAP_SERVER, - (eap_constructor_t)eap_ttls_create_server); - charon->eap->add_method(charon->eap, EAP_TTLS, 0, EAP_PEER, - (eap_constructor_t)eap_ttls_create_peer); - return &this->plugin; } diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c index 835cd7306..3c46993b7 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c @@ -135,7 +135,7 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this) } METHOD(tls_application_t, process, status_t, - private_eap_ttls_server_t *this, tls_reader_t *reader) + private_eap_ttls_server_t *this, bio_reader_t *reader) { chunk_t data = chunk_empty; status_t status; @@ -284,7 +284,7 @@ METHOD(tls_application_t, process, status_t, } METHOD(tls_application_t, build, status_t, - private_eap_ttls_server_t *this, tls_writer_t *writer) + private_eap_ttls_server_t *this, bio_writer_t *writer) { chunk_t data; eap_code_t code; diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index 4ba29472d..cfb51933c 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,6 +203,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -216,11 +220,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/farp/farp_listener.c b/src/libcharon/plugins/farp/farp_listener.c index 8eed49778..d1df4cc27 100644 --- a/src/libcharon/plugins/farp/farp_listener.c +++ b/src/libcharon/plugins/farp/farp_listener.c @@ -15,7 +15,7 @@ #include "farp_listener.h" -#include <utils/hashtable.h> +#include <utils/linked_list.h> #include <threading/rwlock.h> typedef struct private_farp_listener_t private_farp_listener_t; @@ -31,9 +31,9 @@ struct private_farp_listener_t { farp_listener_t public; /** - * Hashtable with active virtual IPs + * List with entry_t */ - hashtable_t *ips; + linked_list_t *entries; /** * RWlock for IP list @@ -42,88 +42,99 @@ struct private_farp_listener_t { }; /** - * Hashtable hash function + * Traffic selector cache entry */ -static u_int hash(host_t *key) +typedef struct { + /** list of local selectors */ + linked_list_t *local; + /** list of remote selectors */ + linked_list_t *remote; + /** reqid of CHILD_SA */ + u_int32_t reqid; +} entry_t; + +METHOD(listener_t, child_updown, bool, + private_farp_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool up) { - return chunk_hash(key->get_address(key)); -} - -/** - * Hashtable equals function - */ -static bool equals(host_t *a, host_t *b) -{ - return a->ip_equals(a, b); -} + enumerator_t *enumerator; + entry_t *entry; -METHOD(listener_t, ike_updown, bool, - private_farp_listener_t *this, ike_sa_t *ike_sa, bool up) -{ - if (!up) + if (up) { - host_t *ip; - - ip = ike_sa->get_virtual_ip(ike_sa, FALSE); - if (ip) - { - this->lock->write_lock(this->lock); - ip = this->ips->remove(this->ips, ip); - this->lock->unlock(this->lock); - DESTROY_IF(ip); - } + INIT(entry, + .local = child_sa->get_traffic_selectors(child_sa, TRUE), + .remote = child_sa->get_traffic_selectors(child_sa, FALSE), + .reqid = child_sa->get_reqid(child_sa), + ); + entry->local = entry->local->clone_offset(entry->local, + offsetof(traffic_selector_t, clone)); + entry->remote = entry->remote->clone_offset(entry->remote, + offsetof(traffic_selector_t, clone)); + + this->lock->write_lock(this->lock); + this->entries->insert_last(this->entries, entry); + this->lock->unlock(this->lock); } - return TRUE; -} - -METHOD(listener_t, message_hook, bool, - private_farp_listener_t *this, ike_sa_t *ike_sa, - message_t *message, bool incoming) -{ - if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && - message->get_exchange_type(message) == IKE_AUTH && - !message->get_request(message)) + else { - host_t *ip; - - ip = ike_sa->get_virtual_ip(ike_sa, FALSE); - if (ip) + this->lock->write_lock(this->lock); + enumerator = this->entries->create_enumerator(this->entries); + while (enumerator->enumerate(enumerator, &entry)) { - ip = ip->clone(ip); - this->lock->write_lock(this->lock); - ip = this->ips->put(this->ips, ip, ip); - this->lock->unlock(this->lock); - DESTROY_IF(ip); + if (entry->reqid == child_sa->get_reqid(child_sa)) + { + this->entries->remove_at(this->entries, enumerator); + entry->local->destroy_offset(entry->local, + offsetof(traffic_selector_t, destroy)); + entry->remote->destroy_offset(entry->remote, + offsetof(traffic_selector_t, destroy)); + free(entry); + } } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } return TRUE; } -METHOD(farp_listener_t, is_active, bool, - private_farp_listener_t *this, host_t *ip) +METHOD(farp_listener_t, has_tunnel, bool, + private_farp_listener_t *this, host_t *local, host_t *remote) { - bool active; + enumerator_t *entries, *locals, *remotes; + traffic_selector_t *ts; + bool found = FALSE; + entry_t *entry; this->lock->read_lock(this->lock); - active = this->ips->get(this->ips, ip) != NULL; + entries = this->entries->create_enumerator(this->entries); + while (!found && entries->enumerate(entries, &entry)) + { + remotes = entry->remote->create_enumerator(entry->remote); + while (!found && remotes->enumerate(remotes, &ts)) + { + if (ts->includes(ts, remote)) + { + locals = entry->local->create_enumerator(entry->local); + while (!found && locals->enumerate(locals, &ts)) + { + found = ts->includes(ts, local); + } + locals->destroy(locals); + } + } + remotes->destroy(remotes); + } + entries->destroy(entries); this->lock->unlock(this->lock); - return active; + + return found; } METHOD(farp_listener_t, destroy, void, private_farp_listener_t *this) { - enumerator_t *enumerator; - host_t *key, *value; - - enumerator = this->ips->create_enumerator(this->ips); - while (enumerator->enumerate(enumerator, &key, &value)) - { - value->destroy(value); - } - enumerator->destroy(enumerator); - this->ips->destroy(this->ips); - + this->entries->destroy(this->entries); this->lock->destroy(this->lock); free(this); } @@ -138,14 +149,12 @@ farp_listener_t *farp_listener_create() INIT(this, .public = { .listener = { - .ike_updown = _ike_updown, - .message = _message_hook, + .child_updown = _child_updown, }, - .is_active = _is_active, + .has_tunnel = _has_tunnel, .destroy = _destroy, }, - .ips = hashtable_create((hashtable_hash_t)hash, - (hashtable_equals_t)equals, 8), + .entries = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); diff --git a/src/libcharon/plugins/farp/farp_listener.h b/src/libcharon/plugins/farp/farp_listener.h index bd96d7a1c..3155f60e2 100644 --- a/src/libcharon/plugins/farp/farp_listener.h +++ b/src/libcharon/plugins/farp/farp_listener.h @@ -37,12 +37,13 @@ struct farp_listener_t { listener_t listener; /** - * Check if a given IP is currently used as virtual IP by a peer. + * Check if we have a tunnel between two IP addresses. * - * @param ip IP to check - * @return TRUE if IP is an active virtual IP + * @param local local IP + * @param remote remote IP + * @return TRUE if a tunnel is active */ - bool (*is_active)(farp_listener_t *this, host_t *ip); + bool (*has_tunnel)(farp_listener_t *this, host_t *local, host_t *remote); /** * Destroy a farp_listener_t. diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c index a904a6538..587a3a74e 100644 --- a/src/libcharon/plugins/farp/farp_spoofer.c +++ b/src/libcharon/plugins/farp/farp_spoofer.c @@ -108,7 +108,7 @@ static job_requeue_t receive_arp(private_farp_spoofer_t *this) arp_t arp; int oldstate; ssize_t len; - host_t *ip; + host_t *local, *remote; oldstate = thread_cancelability(TRUE); len = recvfrom(this->skt, &arp, sizeof(arp), 0, @@ -117,16 +117,16 @@ static job_requeue_t receive_arp(private_farp_spoofer_t *this) if (len == sizeof(arp)) { - ip = host_create_from_chunk(AF_INET, + local = host_create_from_chunk(AF_INET, + chunk_create((char*)&arp.sender_ip, 4), 0); + remote = host_create_from_chunk(AF_INET, chunk_create((char*)&arp.target_ip, 4), 0); - if (ip) + if (this->listener->has_tunnel(this->listener, local, remote)) { - if (this->listener->is_active(this->listener, ip)) - { - send_arp(this, &arp, &addr); - } - ip->destroy(ip); + send_arp(this, &arp, &addr); } + local->destroy(local); + remote->destroy(remote); } return JOB_REQUEUE_DIRECT; @@ -189,8 +189,8 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener) return NULL; } - this->job = callback_job_create((callback_job_cb_t)receive_arp, - this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)receive_arp, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); return &this->public; diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am index 0df1b8d91..bc1b49d48 100644 --- a/src/libcharon/plugins/ha/Makefile.am +++ b/src/libcharon/plugins/ha/Makefile.am @@ -1,5 +1,5 @@ -INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \ +INCLUDES = -I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index fe72c5c8e..c66a550cd 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -194,6 +194,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +205,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +222,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +272,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -276,7 +283,7 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \ +INCLUDES = -I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/libcharon AM_CFLAGS = -rdynamic -DIPSEC_PIDDIR=\"${piddir}\" diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c index 9ff3fd5ff..970a8a2b9 100644 --- a/src/libcharon/plugins/ha/ha_cache.c +++ b/src/libcharon/plugins/ha/ha_cache.c @@ -196,22 +196,37 @@ METHOD(ha_cache_t, delete_, void, */ static status_t rekey_children(ike_sa_t *ike_sa) { - iterator_t *iterator; + enumerator_t *enumerator; child_sa_t *child_sa; status_t status = SUCCESS; - iterator = ike_sa->create_child_sa_iterator(ike_sa); - while (iterator->iterate(iterator, (void**)&child_sa)) + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, (void**)&child_sa)) { - DBG1(DBG_CFG, "resyncing CHILD_SA"); - status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + if (ike_sa->supports_extension(ike_sa, EXT_MS_WINDOWS) && + ike_sa->has_condition(ike_sa, COND_NAT_THERE)) + { + /* NATed Windows clients don't accept CHILD_SA rekeying, but fail + * with an "invalid situation" error. We just close the CHILD_SA, + * Windows will reestablish it immediately if required. */ + DBG1(DBG_CFG, "resyncing CHILD_SA using a delete"); + status = ike_sa->delete_child_sa(ike_sa, + child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + } + else + { + DBG1(DBG_CFG, "resyncing CHILD_SA using a rekey"); + status = ike_sa->rekey_child_sa(ike_sa, + child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + } if (status == DESTROY_ME) { break; } } - iterator->destroy(iterator); + enumerator->destroy(enumerator); return status; } @@ -228,7 +243,7 @@ static void rekey_segment(private_ha_cache_t *this, u_int segment) list = linked_list_create(); enumerator = charon->ike_sa_manager->create_enumerator( - charon->ike_sa_manager); + charon->ike_sa_manager, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && @@ -355,8 +370,8 @@ ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket, { /* request a resync as soon as we are up */ lib->scheduler->schedule_job(lib->scheduler, (job_t*) - callback_job_create((callback_job_cb_t)request_resync, - this, NULL, NULL), 1); + callback_job_create_with_prio((callback_job_cb_t)request_resync, + this, NULL, NULL, JOB_PRIO_CRITICAL), 1); } return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c index 15f7824f9..9c99807ed 100644 --- a/src/libcharon/plugins/ha/ha_ctl.c +++ b/src/libcharon/plugins/ha/ha_ctl.c @@ -141,8 +141,8 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache) strerror(errno)); } - this->job = callback_job_create((callback_job_cb_t)dispatch_fifo, - this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 0d0df8dd1..994f91d20 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -220,7 +220,7 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa_t *ike_sa = NULL; peer_cfg_t *peer_cfg = NULL; auth_cfg_t *auth; - bool received_vip = FALSE; + bool received_vip = FALSE, first_peer_addr = TRUE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -260,9 +260,13 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa->set_virtual_ip(ike_sa, FALSE, value.host); received_vip = TRUE; break; - case HA_ADDITIONAL_ADDR: - ike_sa->add_additional_address(ike_sa, - value.host->clone(value.host)); + case HA_PEER_ADDR: + if (first_peer_addr) + { + ike_sa->clear_peer_addresses(ike_sa); + first_peer_addr = FALSE; + } + ike_sa->add_peer_address(ike_sa, value.host->clone(value.host)); break; case HA_CONFIG_NAME: peer_cfg = charon->backends->get_peer_cfg_by_name( @@ -281,6 +285,10 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_extension(ike_sa, value.u32, EXT_NATT); set_extension(ike_sa, value.u32, EXT_MOBIKE); set_extension(ike_sa, value.u32, EXT_HASH_AND_URL); + set_extension(ike_sa, value.u32, EXT_MULTIPLE_AUTH); + set_extension(ike_sa, value.u32, EXT_STRONGSWAN); + set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION); + set_extension(ike_sa, value.u32, EXT_MS_WINDOWS); break; case HA_CONDITIONS: set_condition(ike_sa, value.u32, COND_NAT_ANY); @@ -290,6 +298,7 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_condition(ike_sa, value.u32, COND_EAP_AUTHENTICATED); set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN); set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); + set_condition(ike_sa, value.u32, COND_STALE); break; default: break; @@ -872,8 +881,8 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, .kernel = kernel, .attr = attr, ); - this->job = callback_job_create((callback_job_cb_t)dispatch, - this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); return &this->public; diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index 1efba4e8f..e818aec9c 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -143,7 +143,7 @@ METHOD(listener_t, ike_updown, bool, if (up) { - iterator_t *iterator; + enumerator_t *enumerator; peer_cfg_t *peer_cfg; u_int32_t extension, condition; host_t *addr; @@ -158,11 +158,16 @@ METHOD(listener_t, ike_updown, bool, | copy_condition(ike_sa, COND_NAT_FAKE) | copy_condition(ike_sa, COND_EAP_AUTHENTICATED) | copy_condition(ike_sa, COND_CERTREQ_SEEN) - | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR); + | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR) + | copy_condition(ike_sa, COND_STALE); extension = copy_extension(ike_sa, EXT_NATT) | copy_extension(ike_sa, EXT_MOBIKE) - | copy_extension(ike_sa, EXT_HASH_AND_URL); + | copy_extension(ike_sa, EXT_HASH_AND_URL) + | copy_extension(ike_sa, EXT_MULTIPLE_AUTH) + | copy_extension(ike_sa, EXT_STRONGSWAN) + | copy_extension(ike_sa, EXT_EAP_ONLY_AUTHENTICATION) + | copy_extension(ike_sa, EXT_MS_WINDOWS); id = ike_sa->get_id(ike_sa); @@ -180,12 +185,12 @@ METHOD(listener_t, ike_updown, bool, m->add_attribute(m, HA_CONDITIONS, condition); m->add_attribute(m, HA_EXTENSIONS, extension); m->add_attribute(m, HA_CONFIG_NAME, peer_cfg->get_name(peer_cfg)); - iterator = ike_sa->create_additional_address_iterator(ike_sa); - while (iterator->iterate(iterator, (void**)&addr)) + enumerator = ike_sa->create_peer_address_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, (void**)&addr)) { - m->add_attribute(m, HA_ADDITIONAL_ADDR, addr); + m->add_attribute(m, HA_PEER_ADDR, addr); } - iterator->destroy(iterator); + enumerator->destroy(enumerator); } else { diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c index 56bdbf454..2377a2630 100644 --- a/src/libcharon/plugins/ha/ha_kernel.c +++ b/src/libcharon/plugins/ha/ha_kernel.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Martin Willi + * Copyright (C) 2009-2011 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,7 +18,7 @@ typedef u_int32_t u32; typedef u_int8_t u8; -#include <linux/jhash.h> +#include <sys/utsname.h> #include <string.h> #include <errno.h> #include <unistd.h> @@ -28,6 +28,16 @@ typedef u_int8_t u8; #define CLUSTERIP_DIR "/proc/net/ipt_CLUSTERIP" +/** + * Versions of jhash used in the Linux kernel + */ +typedef enum { + /* old variant, http://burtleburtle.net/bob/c/lookup2.c */ + JHASH_LOOKUP2, + /* new variant, http://burtleburtle.net/bob/c/lookup3.c, since 2.6.37 */ + JHASH_LOOKUP3, +} jhash_version_t; + typedef struct private_ha_kernel_t private_ha_kernel_t; /** @@ -41,17 +51,98 @@ struct private_ha_kernel_t { ha_kernel_t public; /** - * Init value for jhash + * Total number of ClusterIP segments */ - u_int initval; + u_int count; /** - * Total number of ClusterIP segments + * jhash version the kernel uses */ - u_int count; + jhash_version_t version; }; /** + * Get the jhash version based on the uname().release + */ +static jhash_version_t get_jhash_version() +{ + struct utsname utsname; + int a, b, c; + + if (uname(&utsname) == 0) + { + switch (sscanf(utsname.release, "%d.%d.%d", &a, &b, &c)) + { + case 3: + if (a == 2 && b == 6) + { + if (c < 37) + { + DBG1(DBG_CFG, "detected Linux %d.%d.%d, using old " + "jhash", a, b, c); + return JHASH_LOOKUP2; + } + DBG1(DBG_CFG, "detected Linux %d.%d.%d, using new " + "jhash", a, b, c); + return JHASH_LOOKUP3; + } + /* FALL */ + case 2: + DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash", a, b); + return JHASH_LOOKUP3; + default: + break; + } + } + DBG1(DBG_CFG, "detecting Linux version failed, using new jhash"); + return JHASH_LOOKUP3; +} + +/** + * Rotate 32 bit word x by k bits + */ +#define jhash_rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/** + * jhash algorithm of two words, as used in kernel (using 0 as initval) + */ +static u_int32_t jhash(jhash_version_t version, u_int32_t a, u_int32_t b) +{ + u_int32_t c = 0; + + switch (version) + { + case JHASH_LOOKUP2: + a += 0x9e3779b9; + b += 0x9e3779b9; + + a -= b; a -= c; a ^= (c >> 13); + b -= c; b -= a; b ^= (a << 8); + c -= a; c -= b; c ^= (b >> 13); + a -= b; a -= c; a ^= (c >> 12); + b -= c; b -= a; b ^= (a << 16); + c -= a; c -= b; c ^= (b >> 5); + a -= b; a -= c; a ^= (c >> 3); + b -= c; b -= a; b ^= (a << 10); + c -= a; c -= b; c ^= (b >> 15); + break; + case JHASH_LOOKUP3: + a += 0xdeadbeef; + b += 0xdeadbeef; + + c ^= b; c -= jhash_rot(b, 14); + a ^= c; a -= jhash_rot(c, 11); + b ^= a; b -= jhash_rot(a, 25); + c ^= b; c -= jhash_rot(b, 16); + a ^= c; a -= jhash_rot(c, 4); + b ^= a; b -= jhash_rot(a, 14); + c ^= b; c -= jhash_rot(b, 24); + break; + } + return c; +} + +/** * Segmentate a calculated hash */ static u_int hash2segment(private_ha_kernel_t *this, u_int64_t hash) @@ -78,7 +169,7 @@ METHOD(ha_kernel_t, get_segment, u_int, u_int32_t addr; addr = host2int(host); - hash = jhash_1word(ntohl(addr), this->initval); + hash = jhash(this->version, ntohl(addr), 0); return hash2segment(this, hash); } @@ -90,7 +181,7 @@ METHOD(ha_kernel_t, get_segment_spi, u_int, u_int32_t addr; addr = host2int(host); - hash = jhash_2words(ntohl(addr), ntohl(spi), this->initval); + hash = jhash(this->version, ntohl(addr), ntohl(spi)); return hash2segment(this, hash); } @@ -100,7 +191,7 @@ METHOD(ha_kernel_t, get_segment_int, u_int, { unsigned long hash; - hash = jhash_1word(ntohl(n), this->initval); + hash = jhash(this->version, ntohl(n), 0); return hash2segment(this, hash); } @@ -123,7 +214,7 @@ static void enable_disable(private_ha_kernel_t *this, u_int segment, file, strerror(errno)); return; } - if (write(fd, cmd, strlen(cmd) == -1)) + if (write(fd, cmd, strlen(cmd)) == -1) { DBG1(DBG_CFG, "writing to CLUSTERIP file '%s' failed: %s", file, strerror(errno)); @@ -149,6 +240,7 @@ static segment_mask_t get_active(private_ha_kernel_t *this, char *file) return 0; } len = read(fd, buf, sizeof(buf)-1); + close(fd); if (len == -1) { DBG1(DBG_CFG, "reading from CLUSTERIP file '%s' failed: %s", @@ -182,11 +274,14 @@ METHOD(ha_kernel_t, activate, void, char *file; enumerator = enumerator_create_directory(CLUSTERIP_DIR); - while (enumerator->enumerate(enumerator, NULL, &file, NULL)) + if (enumerator) { - enable_disable(this, segment, file, TRUE); + while (enumerator->enumerate(enumerator, NULL, &file, NULL)) + { + enable_disable(this, segment, file, TRUE); + } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); } METHOD(ha_kernel_t, deactivate, void, @@ -196,11 +291,14 @@ METHOD(ha_kernel_t, deactivate, void, char *file; enumerator = enumerator_create_directory(CLUSTERIP_DIR); - while (enumerator->enumerate(enumerator, NULL, &file, NULL)) + if (enumerator) { - enable_disable(this, segment, file, FALSE); + while (enumerator->enumerate(enumerator, NULL, &file, NULL)) + { + enable_disable(this, segment, file, FALSE); + } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); } /** @@ -214,23 +312,26 @@ static void disable_all(private_ha_kernel_t *this) int i; enumerator = enumerator_create_directory(CLUSTERIP_DIR); - while (enumerator->enumerate(enumerator, NULL, &file, NULL)) + if (enumerator) { - if (chown(file, charon->uid, charon->gid) != 0) + while (enumerator->enumerate(enumerator, NULL, &file, NULL)) { - DBG1(DBG_CFG, "changing ClusterIP permissions failed: %s", - strerror(errno)); - } - active = get_active(this, file); - for (i = 1; i <= this->count; i++) - { - if (active & SEGMENTS_BIT(i)) + if (chown(file, charon->uid, charon->gid) != 0) { - enable_disable(this, i, file, FALSE); + DBG1(DBG_CFG, "changing ClusterIP permissions failed: %s", + strerror(errno)); + } + active = get_active(this, file); + for (i = 1; i <= this->count; i++) + { + if (active & SEGMENTS_BIT(i)) + { + enable_disable(this, i, file, FALSE); + } } } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); } METHOD(ha_kernel_t, destroy, void, @@ -255,7 +356,7 @@ ha_kernel_t *ha_kernel_create(u_int count) .deactivate = _deactivate, .destroy = _destroy, }, - .initval = 0, + .version = get_jhash_version(), .count = count, ); diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index f98f78dd4..810109a5d 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -184,7 +184,7 @@ METHOD(ha_message_t, add_attribute, void, case HA_REMOTE_ADDR: case HA_LOCAL_VIP: case HA_REMOTE_VIP: - case HA_ADDITIONAL_ADDR: + case HA_PEER_ADDR: { host_encoding_t *enc; host_t *host; @@ -386,7 +386,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, case HA_REMOTE_ADDR: case HA_LOCAL_VIP: case HA_REMOTE_VIP: - case HA_ADDITIONAL_ADDR: + case HA_PEER_ADDR: { host_encoding_t *enc; diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index 1f8eabd62..d0323d7a0 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -98,8 +98,8 @@ enum ha_message_attribute_t { HA_LOCAL_VIP, /** host_t*, remote virtual IP */ HA_REMOTE_VIP, - /** host_t*, additional MOBIKE peer address */ - HA_ADDITIONAL_ADDR, + /** host_t*, known peer addresses (used for MOBIKE) */ + HA_PEER_ADDR, /** u_int8_t, initiator of an exchange, TRUE for local */ HA_INITIATOR, /** chunk_t, initiators nonce */ diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index 7c7bef851..c5a180683 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -166,7 +166,8 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, if (changes) { - enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); + enumerator = charon->ike_sa_manager->create_enumerator( + charon->ike_sa_manager, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { if (ike_sa->get_state(ike_sa) != old) @@ -279,8 +280,8 @@ static job_requeue_t watchdog(private_ha_segments_t *this) */ static void start_watchdog(private_ha_segments_t *this) { - this->job = callback_job_create((callback_job_cb_t)watchdog, - this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)watchdog, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); } diff --git a/src/libcharon/plugins/ha/ha_segments.h b/src/libcharon/plugins/ha/ha_segments.h index eb9e5c1d5..76da38082 100644 --- a/src/libcharon/plugins/ha/ha_segments.h +++ b/src/libcharon/plugins/ha/ha_segments.h @@ -55,7 +55,7 @@ struct ha_segments_t { * Activate a set of IKE_SAs identified by a segment. * * @param segment numerical segment to takeover, 0 for all - * @param notify wheter to notify other nodes about activation + * @param notify whether to notify other nodes about activation */ void (*activate)(ha_segments_t *this, u_int segment, bool notify); @@ -63,7 +63,7 @@ struct ha_segments_t { * Deactivate a set of IKE_SAs identified by a segment. * * @param segment numerical segment to takeover, 0 for all - * @param notify wheter to notify other nodes about deactivation + * @param notify whether to notify other nodes about deactivation */ void (*deactivate)(ha_segments_t *this, u_int segment, bool notify); diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c index 086178442..c02cf1021 100644 --- a/src/libcharon/plugins/ha/ha_socket.c +++ b/src/libcharon/plugins/ha/ha_socket.c @@ -105,8 +105,8 @@ METHOD(ha_socket_t, push, void, .fd = this->fd, ); - job = callback_job_create((callback_job_cb_t)send_message, - data, (void*)job_data_destroy, NULL); + job = callback_job_create_with_prio((callback_job_cb_t)send_message, + data, (void*)job_data_destroy, NULL, JOB_PRIO_HIGH); lib->processor->queue_job(lib->processor, (job_t*)job); return; } diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in index db3a7c702..56684ee11 100644 --- a/src/libcharon/plugins/led/Makefile.in +++ b/src/libcharon/plugins/led/Makefile.in @@ -191,6 +191,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -199,6 +202,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -215,11 +219,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -263,6 +269,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/led/led_listener.c b/src/libcharon/plugins/led/led_listener.c index 18def8005..4aae2abe5 100644 --- a/src/libcharon/plugins/led/led_listener.c +++ b/src/libcharon/plugins/led/led_listener.c @@ -156,9 +156,9 @@ static void blink_activity(private_led_listener_t *this) { set_led(this->activity, this->activity_max); } - lib->scheduler->schedule_job_ms(lib->scheduler, - (job_t*)callback_job_create((callback_job_cb_t)reset_activity_led, - this, NULL, NULL), this->blink_time); + lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*) + callback_job_create_with_prio((callback_job_cb_t)reset_activity_led, + this, NULL, NULL, JOB_PRIO_CRITICAL), this->blink_time); this->mutex->unlock(this->mutex); } } diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index 1e9a5fe82..bbd20d4b9 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -197,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -205,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -221,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -269,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index 71391d593..6bc6f91e4 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -65,6 +65,16 @@ struct private_load_tester_config_t { char *responder_auth; /** + * Initiator ID to enforce + */ + char *initiator_id; + + /** + * Responder ID to enforce + */ + char *responder_id; + + /** * IKE_SA rekeying delay */ u_int ike_rekey; @@ -75,6 +85,11 @@ struct private_load_tester_config_t { u_int child_rekey; /** + * DPD check delay + */ + u_int dpd_delay; + + /** * incremental numbering of generated configs */ u_int num; @@ -102,24 +117,46 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str, enumerator = enumerator_create_token(str, "|", " "); while (enumerator->enumerate(enumerator, &str)) { + id = NULL; auth = auth_cfg_create(); rnd++; - if (streq(str, "psk")) - { /* PSK authentication, use FQDNs */ - class = AUTH_CLASS_PSK; - if ((local && !num) || (!local && num)) + if (this->initiator_id) + { + if ((local && num) || (!local && !num)) { - id = identification_create_from_string("srv.strongswan.org"); + snprintf(buf, sizeof(buf), this->initiator_id, num, rnd); + id = identification_create_from_string(buf); } - else if (local) + } + if (this->responder_id) + { + if ((local && !num) || (!local && num)) { - snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org", num, rnd); + snprintf(buf, sizeof(buf), this->responder_id, num, rnd); id = identification_create_from_string(buf); } - else + } + + if (streq(str, "psk")) + { /* PSK authentication, use FQDNs */ + class = AUTH_CLASS_PSK; + if (!id) { - id = identification_create_from_string("*.strongswan.org"); + if ((local && !num) || (!local && num)) + { + id = identification_create_from_string("srv.strongswan.org"); + } + else if (local) + { + snprintf(buf, sizeof(buf), "c%d-r%d.strongswan.org", + num, rnd); + id = identification_create_from_string(buf); + } + else + { + id = identification_create_from_string("*.strongswan.org"); + } } } else if (strneq(str, "eap", strlen("eap"))) @@ -133,14 +170,18 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str, auth->add(auth, AUTH_RULE_EAP_TYPE, type); } } - if (local && num) + if (!id) { - snprintf(buf, sizeof(buf), "1%.10d%.4d@strongswan.org", num, rnd); - id = identification_create_from_string(buf); - } - else - { - id = identification_create_from_encoding(ID_ANY, chunk_empty); + if (local && num) + { + snprintf(buf, sizeof(buf), "1%.10d%.4d@strongswan.org", + num, rnd); + id = identification_create_from_string(buf); + } + else + { + id = identification_create_from_encoding(ID_ANY, chunk_empty); + } } } else @@ -152,21 +193,24 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str, } /* certificate authentication, use distinguished names */ class = AUTH_CLASS_PUBKEY; - if ((local && !num) || (!local && num)) - { - id = identification_create_from_string( - "CN=srv, OU=load-test, O=strongSwan"); - } - else if (local) + if (!id) { - snprintf(buf, sizeof(buf), - "CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd); - id = identification_create_from_string(buf); - } - else - { - id = identification_create_from_string( - "CN=*, OU=load-test, O=strongSwan"); + if ((local && !num) || (!local && num)) + { + id = identification_create_from_string( + "CN=srv, OU=load-test, O=strongSwan"); + } + else if (local) + { + snprintf(buf, sizeof(buf), + "CN=c%d-r%d, OU=load-test, O=strongSwan", num, rnd); + id = identification_create_from_string(buf); + } + else + { + id = identification_create_from_string( + "CN=*, OU=load-test, O=strongSwan"); + } } } auth->add(auth, AUTH_RULE_AUTH_CLASS, class); @@ -209,7 +253,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) CERT_SEND_IF_ASKED, UNIQUE_NO, 1, /* keytries */ this->ike_rekey, 0, /* rekey, reauth */ 0, this->ike_rekey, /* jitter, overtime */ - FALSE, 0, /* mobike, dpddelay */ + FALSE, this->dpd_delay, /* mobike, dpddelay */ this->vip ? this->vip->clone(this->vip) : NULL, this->pool, FALSE, NULL, NULL); if (num) @@ -236,21 +280,15 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) return peer_cfg; } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_load_tester_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_load_tester_config_t *this, + identification_t *me, identification_t *other) { return enumerator_create_single(this->peer_cfg, NULL); } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_load_tester_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_load_tester_config_t *this, host_t *me, host_t *other) { ike_cfg_t *ike_cfg; @@ -258,11 +296,8 @@ static enumerator_t* create_ike_cfg_enumerator(private_load_tester_config_t *thi return enumerator_create_single(ike_cfg, NULL); } -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_load_tester_config_t *this, - char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_load_tester_config_t *this, char *name) { if (streq(name, "load-test")) { @@ -271,10 +306,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_load_tester_config_t *this, return NULL; } -/** - * Implementation of load_tester_config_t.destroy. - */ -static void destroy(private_load_tester_config_t *this) +METHOD(load_tester_config_t, destroy, void, + private_load_tester_config_t *this) { this->peer_cfg->destroy(this->peer_cfg); DESTROY_IF(this->proposal); @@ -287,14 +320,20 @@ static void destroy(private_load_tester_config_t *this) */ load_tester_config_t *load_tester_config_create() { - private_load_tester_config_t *this = malloc_thing(private_load_tester_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.destroy = (void(*)(load_tester_config_t*))destroy; + private_load_tester_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .destroy = _destroy, + }, + .num = 1, + ); - this->vip = NULL; if (lib->settings->get_bool(lib->settings, "charon.plugins.load-tester.request_virtual_ip", FALSE)) { @@ -317,16 +356,21 @@ load_tester_config_t *load_tester_config_create() "charon.plugins.load-tester.ike_rekey", 0); this->child_rekey = lib->settings->get_int(lib->settings, "charon.plugins.load-tester.child_rekey", 600); + this->dpd_delay = lib->settings->get_int(lib->settings, + "charon.plugins.load-tester.dpd_delay", 0); this->initiator_auth = lib->settings->get_str(lib->settings, "charon.plugins.load-tester.initiator_auth", "pubkey"); this->responder_auth = lib->settings->get_str(lib->settings, "charon.plugins.load-tester.responder_auth", "pubkey"); + this->initiator_id = lib->settings->get_str(lib->settings, + "charon.plugins.load-tester.initiator_id", NULL); + this->responder_id = lib->settings->get_str(lib->settings, + "charon.plugins.load-tester.responder_id", NULL); this->port = lib->settings->get_int(lib->settings, "charon.plugins.load-tester.dynamic_port", 0); - this->num = 1; this->peer_cfg = generate_config(this, 0); return &this->public; diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c index 890703c1a..c34ea73c5 100644 --- a/src/libcharon/plugins/load_tester/load_tester_creds.c +++ b/src/libcharon/plugins/load_tester/load_tester_creds.c @@ -49,9 +49,14 @@ struct private_load_tester_creds_t { u_int32_t serial; /** - * Preshared key + * Preshared key for IKE */ - shared_key_t *shared; + shared_key_t *psk; + + /** + * Password for EAP + */ + shared_key_t *pwd; }; /** @@ -131,7 +136,7 @@ CwMLbJ7vQqwPHXRitDmNkEOK9H+vRnDf -----END CERTIFICATE----- */ -char cert[] = { +static char cert[] = { 0x30,0x82,0x01,0xf4,0x30,0x82,0x01,0x5d,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x00, 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30, 0x37,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x73,0x72,0x76,0x31, @@ -168,17 +173,17 @@ char cert[] = { /** - * A preshared key + * Default IKE preshared key */ -static char psk[] = { - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 -}; +static char *default_psk = "default-psk"; /** - * Implements credential_set_t.create_private_enumerator + * Default EAP password for EAP */ -static enumerator_t* create_private_enumerator(private_load_tester_creds_t *this, - key_type_t type, identification_t *id) +static char *default_pwd = "default-pwd"; + +METHOD(credential_set_t, create_private_enumerator, enumerator_t*, + private_load_tester_creds_t *this, key_type_t type, identification_t *id) { if (this->private == NULL) { @@ -198,12 +203,9 @@ static enumerator_t* create_private_enumerator(private_load_tester_creds_t *this return enumerator_create_single(this->private, NULL); } -/** - * Implements credential_set_t.create_cert_enumerator - */ -static enumerator_t* create_cert_enumerator(private_load_tester_creds_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_load_tester_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) { certificate_t *peer_cert; public_key_t *peer_key, *ca_key; @@ -265,49 +267,87 @@ static enumerator_t* create_cert_enumerator(private_load_tester_creds_t *this, } /** - * Implements credential_set_t.create_shared_enumerator + * Filter function for shared keys, returning ID matches */ -static enumerator_t* create_shared_enumerator(private_load_tester_creds_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) +static bool shared_filter(void *null, shared_key_t **in, shared_key_t **out, + void **un1, id_match_t *me, void **un2, id_match_t *other) +{ + *out = *in; + if (me) + { + *me = ID_MATCH_ANY; + } + if (other) + { + *other = ID_MATCH_ANY; + } + return TRUE; +} + +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_load_tester_creds_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) { - return enumerator_create_single(this->shared, NULL); + shared_key_t *shared; + + switch (type) + { + case SHARED_IKE: + shared = this->psk; + break; + case SHARED_EAP: + shared = this->pwd; + break; + default: + return NULL; + } + return enumerator_create_filter(enumerator_create_single(shared, NULL), + (void*)shared_filter, NULL, NULL); } -/** - * Implementation of load_tester_creds_t.destroy - */ -static void destroy(private_load_tester_creds_t *this) +METHOD(load_tester_creds_t, destroy, void, + private_load_tester_creds_t *this) { DESTROY_IF(this->private); DESTROY_IF(this->ca); - this->shared->destroy(this->shared); + this->psk->destroy(this->psk); + this->pwd->destroy(this->pwd); free(this); } load_tester_creds_t *load_tester_creds_create() { - private_load_tester_creds_t *this = malloc_thing(private_load_tester_creds_t); - - this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))create_shared_enumerator; - this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))create_private_enumerator; - this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))create_cert_enumerator; - this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null; - this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop; - this->public.destroy = (void(*) (load_tester_creds_t*))destroy; - - this->private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, - BUILD_BLOB_ASN1_DER, chunk_create(private, sizeof(private)), - BUILD_END); + private_load_tester_creds_t *this; + char *pwd, *psk; - this->ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, chunk_create(cert, sizeof(cert)), - BUILD_X509_FLAG, X509_CA, - BUILD_END); + psk = lib->settings->get_str(lib->settings, + "charon.plugins.load-tester.preshared_key", default_psk); + pwd = lib->settings->get_str(lib->settings, + "charon.plugins.load-tester.eap_password", default_pwd); - this->shared = shared_key_create(SHARED_IKE, - chunk_clone(chunk_create(psk, sizeof(psk)))); - this->serial = 0; + INIT(this, + .public = { + .credential_set = { + .create_shared_enumerator = _create_shared_enumerator, + .create_private_enumerator = _create_private_enumerator, + .create_cert_enumerator = _create_cert_enumerator, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, + BUILD_BLOB_ASN1_DER, chunk_create(private, sizeof(private)), + BUILD_END), + .ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, chunk_create(cert, sizeof(cert)), + BUILD_X509_FLAG, X509_CA, + BUILD_END), + .psk = shared_key_create(SHARED_IKE, + chunk_clone(chunk_create(psk, strlen(psk)))), + .pwd = shared_key_create(SHARED_EAP, + chunk_clone(chunk_create(pwd, strlen(pwd)))), + ); return &this->public; } diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index fdec5300e..440197260 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -35,75 +35,75 @@ struct private_load_tester_ipsec_t { }; METHOD(kernel_ipsec_t, get_spi, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) { *spi = ++this->spi; return SUCCESS; } METHOD(kernel_ipsec_t, get_cpi, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t reqid, u_int16_t *cpi) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t reqid, u_int16_t *cpi) { return FAILED; } METHOD(kernel_ipsec_t, add_sa, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, - u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, - u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, - u_int16_t cpi, bool encap, bool esn, bool inbound, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, + u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, + u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool encap, bool esn, bool inbound, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts) { return SUCCESS; } METHOD(kernel_ipsec_t, update_sa, status_t, - private_load_tester_ipsec_t *this, u_int32_t spi, u_int8_t protocol, - u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, - host_t *new_dst, bool encap, bool new_encap, mark_t mark) + private_load_tester_ipsec_t *this, u_int32_t spi, u_int8_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, + host_t *new_dst, bool encap, bool new_encap, mark_t mark) { return SUCCESS; } METHOD(kernel_ipsec_t, query_sa, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes) { return NOT_SUPPORTED; } METHOD(kernel_ipsec_t, del_sa, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark) { return SUCCESS; } METHOD(kernel_ipsec_t, add_policy, status_t, - private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts, - policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, - mark_t mark, bool routed) + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa, + mark_t mark, policy_priority_t priority) { return SUCCESS; } METHOD(kernel_ipsec_t, query_policy, status_t, - private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, - u_int32_t *use_time) + private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { - *use_time = time_monotonic(NULL); + *use_time = 1; return SUCCESS; } METHOD(kernel_ipsec_t, del_policy, status_t, - private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, - bool unrouted) + private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid, + mark_t mark, policy_priority_t priority) { return SUCCESS; } @@ -115,7 +115,7 @@ METHOD(kernel_ipsec_t, bypass_socket, bool, } METHOD(kernel_ipsec_t, destroy, void, - private_load_tester_ipsec_t *this) + private_load_tester_ipsec_t *this) { free(this); } @@ -136,9 +136,11 @@ load_tester_ipsec_t *load_tester_ipsec_create() .update_sa = _update_sa, .query_sa = _query_sa, .del_sa = _del_sa, + .flush_sas = (void*)return_failed, .add_policy = _add_policy, .query_policy = _query_policy, .del_policy = _del_policy, + .flush_policies = (void*)return_failed, .bypass_socket = _bypass_socket, .destroy = _destroy, }, diff --git a/src/libcharon/plugins/load_tester/load_tester_listener.c b/src/libcharon/plugins/load_tester/load_tester_listener.c index cf6dd0562..7c96f7d97 100644 --- a/src/libcharon/plugins/load_tester/load_tester_listener.c +++ b/src/libcharon/plugins/load_tester/load_tester_listener.c @@ -42,21 +42,25 @@ struct private_load_tester_listener_t { u_int established; /** + * Number of terminated SAs + */ + u_int terminated; + + /** * Shutdown the daemon if we have established this SA count */ u_int shutdown_on; }; -/** - * Implementation of listener_t.ike_state_change - */ -static bool ike_state_change(private_load_tester_listener_t *this, - ike_sa_t *ike_sa, ike_sa_state_t state) +METHOD(listener_t, ike_updown, bool, + private_load_tester_listener_t *this, ike_sa_t *ike_sa, bool up) { - if (state == IKE_ESTABLISHED) + if (up) { ike_sa_id_t *id = ike_sa->get_id(ike_sa); + this->established++; + if (this->delete_after_established) { lib->processor->queue_job(lib->processor, @@ -65,37 +69,48 @@ static bool ike_state_change(private_load_tester_listener_t *this, if (id->is_initiator(id)) { - if (this->shutdown_on == ++this->established) + if (this->shutdown_on == this->established) { DBG1(DBG_CFG, "load-test complete, raising SIGTERM"); kill(0, SIGTERM); } } } + else + { + this->terminated++; + } return TRUE; } -/** - * Implementation of load_tester_listener_t.destroy - */ -static void destroy(private_load_tester_listener_t *this) +METHOD(load_tester_listener_t, get_established, u_int, + private_load_tester_listener_t *this) +{ + return this->established - this->terminated; +} + +METHOD(load_tester_listener_t, destroy, void, + private_load_tester_listener_t *this) { free(this); } load_tester_listener_t *load_tester_listener_create(u_int shutdown_on) { - private_load_tester_listener_t *this = malloc_thing(private_load_tester_listener_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.ike_state_change = (void*)ike_state_change; - this->public.destroy = (void(*) (load_tester_listener_t*))destroy; - - this->delete_after_established = lib->settings->get_bool(lib->settings, - "charon.plugins.load-tester.delete_after_established", FALSE); - - this->shutdown_on = shutdown_on; - this->established = 0; + private_load_tester_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_updown = _ike_updown, + }, + .get_established = _get_established, + .destroy = _destroy, + }, + .delete_after_established = lib->settings->get_bool(lib->settings, + "charon.plugins.load-tester.delete_after_established", FALSE), + .shutdown_on = shutdown_on, + ); return &this->public; } diff --git a/src/libcharon/plugins/load_tester/load_tester_listener.h b/src/libcharon/plugins/load_tester/load_tester_listener.h index b9599294c..2621798c8 100644 --- a/src/libcharon/plugins/load_tester/load_tester_listener.h +++ b/src/libcharon/plugins/load_tester/load_tester_listener.h @@ -36,6 +36,13 @@ struct load_tester_listener_t { listener_t listener; /** + * Get the number of established IKE_SAs. + * + * @return number of SAs currently established + */ + u_int (*get_established)(load_tester_listener_t *this); + + /** * Destroy the backend. */ void (*destroy)(load_tester_listener_t *this); diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index 94115e307..b260a9741 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -68,7 +68,7 @@ struct private_load_tester_plugin_t { int initiators; /** - * currenly running initiators + * currently running initiators */ int running; @@ -78,6 +78,11 @@ struct private_load_tester_plugin_t { int delay; /** + * Throttle initiation if half-open IKE_SA count reached + */ + int init_limit; + + /** * mutex to lock running field */ mutex_t *mutex; @@ -96,10 +101,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) int i, s = 0, ms = 0; this->mutex->lock(this->mutex); - if (!this->running) - { - this->running = this->initiators; - } + this->running++; this->mutex->unlock(this->mutex); if (this->delay) { @@ -113,6 +115,23 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) child_cfg_t *child_cfg = NULL; enumerator_t *enumerator; + if (this->init_limit) + { + while ((charon->ike_sa_manager->get_count(charon->ike_sa_manager) - + this->listener->get_established(this->listener)) > + this->init_limit) + { + if (s) + { + sleep(s); + } + if (ms) + { + usleep(ms * 1000); + } + } + } + peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, "load-test"); if (!peer_cfg) @@ -129,7 +148,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) charon->controller->initiate(charon->controller, peer_cfg, child_cfg->get_ref(child_cfg), - NULL, NULL); + NULL, NULL, 0); if (s) { sleep(s); @@ -141,8 +160,8 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) } this->mutex->lock(this->mutex); this->running--; - this->mutex->unlock(this->mutex); this->condvar->signal(this->condvar); + this->mutex->unlock(this->mutex); return JOB_REQUEUE_NONE; } @@ -206,25 +225,26 @@ plugin_t *load_tester_plugin_create() "charon.plugins.load-tester.iterations", 1), .initiators = lib->settings->get_int(lib->settings, "charon.plugins.load-tester.initiators", 0), + .init_limit = lib->settings->get_int(lib->settings, + "charon.plugins.load-tester.init_limit", 0), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), .config = load_tester_config_create(), .creds = load_tester_creds_create(), - .listener = load_tester_listener_create(shutdown_on), ); lib->crypto->add_dh(lib->crypto, MODP_NULL, plugin_name, (dh_constructor_t)load_tester_diffie_hellman_create); charon->backends->add_backend(charon->backends, &this->config->backend); lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); - charon->bus->add_listener(charon->bus, &this->listener->listener); if (lib->settings->get_bool(lib->settings, "charon.plugins.load-tester.shutdown_when_complete", 0)) { shutdown_on = this->iterations * this->initiators; } - + this->listener = load_tester_listener_create(shutdown_on); + charon->bus->add_listener(charon->bus, &this->listener->listener); if (lib->settings->get_bool(lib->settings, "charon.plugins.load-tester.fake_kernel", FALSE)) @@ -232,12 +252,11 @@ plugin_t *load_tester_plugin_create() hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)load_tester_ipsec_create); } - this->running = 0; for (i = 0; i < this->initiators; i++) { - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create((callback_job_cb_t)do_load_test, - this, NULL, NULL)); + lib->processor->queue_job(lib->processor, (job_t*) + callback_job_create_with_prio((callback_job_cb_t)do_load_test, + this, NULL, NULL, JOB_PRIO_CRITICAL)); } return &this->public.plugin; } diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in index 27e72295c..d2b9d9a34 100644 --- a/src/libcharon/plugins/maemo/Makefile.in +++ b/src/libcharon/plugins/maemo/Makefile.in @@ -196,6 +196,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +207,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +224,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +274,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index 0e9fd8ccc..6675e1d21 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -217,7 +217,7 @@ static void disconnect(private_maemo_service_t *this) id = ike_sa->get_unique_id(ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); charon->controller->terminate_ike(charon->controller, id, - NULL, NULL); + NULL, NULL, 0); } this->current = (g_free(this->current), NULL); this->status = VPN_STATUS_DISCONNECTED; @@ -502,7 +502,8 @@ maemo_service_t *maemo_service_create() } lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL)); + (job_t*)callback_job_create_with_prio((callback_job_cb_t)run, + this, NULL, NULL, JOB_PRIO_CRITICAL)); return &this->public; } diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index 83b457b46..b8983ad21 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -194,6 +194,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +205,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +222,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +272,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index b5672dba9..ee3e95422 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -88,10 +88,8 @@ static traffic_selector_t *ts_from_string(char *str) return traffic_selector_create_dynamic(0, 0, 65535); } -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_medcli_config_t *this, char *name) { enumerator_t *e; peer_cfg_t *peer_cfg, *med_cfg; @@ -192,11 +190,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam return peer_cfg; } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_medcli_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_medcli_config_t *this, host_t *me, host_t *other) { return enumerator_create_single(this->ike, NULL); } @@ -216,10 +211,8 @@ typedef struct { int dpd; } peer_enumerator_t; -/** - * Implementation of peer_enumerator_t.public.enumerate - */ -static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +METHOD(enumerator_t, peer_enumerator_enumerate, bool, + peer_enumerator_t *this, peer_cfg_t **cfg) { char *name, *local_net, *remote_net; chunk_t me, other; @@ -271,31 +264,29 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) return TRUE; } -/** - * Implementation of peer_enumerator_t.public.destroy - */ -static void peer_enumerator_destroy(peer_enumerator_t *this) +METHOD(enumerator_t, peer_enumerator_destroy, void, + peer_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_medcli_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_medcli_config_t *this, identification_t *me, + identification_t *other) { - peer_enumerator_t *e = malloc_thing(peer_enumerator_t); - - e->current = NULL; - e->ike = this->ike; - e->rekey = this->rekey; - e->dpd = this->dpd; - e->public.enumerate = (void*)peer_enumerator_enumerate; - e->public.destroy = (void*)peer_enumerator_destroy; + peer_enumerator_t *e; + + INIT(e, + .public = { + .enumerate = (void*)_peer_enumerator_enumerate, + .destroy = _peer_enumerator_destroy, + }, + .ike = this->ike, + .rekey = this->rekey, + .dpd = this->dpd, + ); /* filter on IDs: NULL or ANY or matching KEY_ID */ e->inner = this->db->query(this->db, @@ -335,7 +326,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg) peer_cfg->get_ref(peer_cfg); enumerator->destroy(enumerator); charon->controller->initiate(charon->controller, - peer_cfg, child_cfg, NULL, NULL); + peer_cfg, child_cfg, NULL, NULL, 0); } else { @@ -345,7 +336,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg) } /** - * schedule initation of all "active" connections + * schedule initiation of all "active" connections */ static void schedule_autoinit(private_medcli_config_t *this) { @@ -374,10 +365,8 @@ static void schedule_autoinit(private_medcli_config_t *this) } } -/** - * Implementation of medcli_config_t.destroy. - */ -static void destroy(private_medcli_config_t *this) +METHOD(medcli_config_t, destroy, void, + private_medcli_config_t *this) { this->ike->destroy(this->ike); free(this); @@ -388,18 +377,23 @@ static void destroy(private_medcli_config_t *this) */ medcli_config_t *medcli_config_create(database_t *db) { - private_medcli_config_t *this = malloc_thing(private_medcli_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.destroy = (void(*)(medcli_config_t*))destroy; - - this->db = db; - this->rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200); - this->dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300); - this->ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT); + private_medcli_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .destroy = _destroy, + }, + .db = db, + .rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200), + .dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300), + .ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", IKEV2_UDP_PORT, + "0.0.0.0", IKEV2_UDP_PORT), + ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); schedule_autoinit(this); diff --git a/src/libcharon/plugins/medcli/medcli_creds.c b/src/libcharon/plugins/medcli/medcli_creds.c index 9729df3f5..9c4a0b756 100644 --- a/src/libcharon/plugins/medcli/medcli_creds.c +++ b/src/libcharon/plugins/medcli/medcli_creds.c @@ -49,11 +49,8 @@ typedef struct { private_key_t *current; } private_enumerator_t; -/** - * Implementation of private_enumerator_t.public.enumerate - */ -static bool private_enumerator_enumerate(private_enumerator_t *this, - private_key_t **key) +METHOD(enumerator_t, private_enumerator_enumerate, bool, + private_enumerator_t *this, private_key_t **key) { chunk_t chunk; @@ -73,21 +70,16 @@ static bool private_enumerator_enumerate(private_enumerator_t *this, return FALSE; } -/** - * Implementation of private_enumerator_t.public.destroy - */ -static void private_enumerator_destroy(private_enumerator_t *this) +METHOD(enumerator_t, private_enumerator_destroy, void, + private_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_private_enumerator. - */ -static enumerator_t* create_private_enumerator(private_medcli_creds_t *this, - key_type_t type, identification_t *id) +METHOD(credential_set_t, create_private_enumerator, enumerator_t*, + private_medcli_creds_t *this, key_type_t type, identification_t *id) { private_enumerator_t *e; @@ -98,10 +90,12 @@ static enumerator_t* create_private_enumerator(private_medcli_creds_t *this, return NULL; } - e = malloc_thing(private_enumerator_t); - e->current = NULL; - e->public.enumerate = (void*)private_enumerator_enumerate; - e->public.destroy = (void*)private_enumerator_destroy; + INIT(e, + .public = { + .enumerate = (void*)_private_enumerator_enumerate, + .destroy = _private_enumerator_destroy, + }, + ); e->inner = this->db->query(this->db, "SELECT PrivateKey FROM ClientConfig WHERE KeyId = ?", DB_BLOB, id->get_encoding(id), @@ -128,11 +122,8 @@ typedef struct { key_type_t type; } cert_enumerator_t; -/** - * Implementation of cert_enumerator_t.public.enumerate - */ -static bool cert_enumerator_enumerate(cert_enumerator_t *this, - certificate_t **cert) +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) { public_key_t *public; chunk_t chunk; @@ -167,22 +158,17 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this, return FALSE; } -/** - * Implementation of cert_enumerator_t.public.destroy - */ -static void cert_enumerator_destroy(cert_enumerator_t *this) +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_cert_enumerator. - */ -static enumerator_t* create_cert_enumerator(private_medcli_creds_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_medcli_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) { cert_enumerator_t *e; @@ -192,11 +178,13 @@ static enumerator_t* create_cert_enumerator(private_medcli_creds_t *this, return NULL; } - e = malloc_thing(cert_enumerator_t); - e->current = NULL; - e->type = key; - e->public.enumerate = (void*)cert_enumerator_enumerate; - e->public.destroy = (void*)cert_enumerator_destroy; + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .type = key, + ); e->inner = this->db->query(this->db, "SELECT PublicKey FROM ClientConfig WHERE KeyId = ? UNION " "SELECT PublicKey FROM MediationServerConfig WHERE KeyId = ? UNION " @@ -213,10 +201,8 @@ static enumerator_t* create_cert_enumerator(private_medcli_creds_t *this, return &e->public; } -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_medcli_creds_t *this) +METHOD(medcli_creds_t, destroy, void, + private_medcli_creds_t *this) { free(this); } @@ -226,17 +212,21 @@ static void destroy(private_medcli_creds_t *this) */ medcli_creds_t *medcli_creds_create(database_t *db) { - private_medcli_creds_t *this = malloc_thing(private_medcli_creds_t); - - this->public.set.create_private_enumerator = (void*)create_private_enumerator; - this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - - this->public.destroy = (void (*)(medcli_creds_t*))destroy; - - this->db = db; + private_medcli_creds_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = _create_private_enumerator, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .db = db, + ); return &this->public; } diff --git a/src/libcharon/plugins/medcli/medcli_listener.c b/src/libcharon/plugins/medcli/medcli_listener.c index 142f02e6c..ba6b3d9d6 100644 --- a/src/libcharon/plugins/medcli/medcli_listener.c +++ b/src/libcharon/plugins/medcli/medcli_listener.c @@ -47,7 +47,7 @@ struct private_medcli_listener_t { }; /** - * Implementation of bus_listener_t.signal. + * Update connection status in the database */ static void set_state(private_medcli_listener_t *this, char *alias, mediated_state_t state) @@ -56,11 +56,9 @@ static void set_state(private_medcli_listener_t *this, char *alias, "UPDATE Connection SET Status = ? WHERE Alias = ?", DB_UINT, state, DB_TEXT, alias); } -/** - * Implementation of listener_t.ike_state_change - */ -static bool ike_state_change(private_medcli_listener_t *this, - ike_sa_t *ike_sa, ike_sa_state_t state) + +METHOD(listener_t, ike_state_change, bool, + private_medcli_listener_t *this, ike_sa_t *ike_sa, ike_sa_state_t state) { if (ike_sa) { @@ -78,11 +76,9 @@ static bool ike_state_change(private_medcli_listener_t *this, return TRUE; } -/** - * Implementation of listener_t.child_state_change - */ -static bool child_state_change(private_medcli_listener_t *this, - ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state) +METHOD(listener_t, child_state_change, bool, + private_medcli_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + child_sa_state_t state) { if (ike_sa && child_sa) { @@ -101,10 +97,8 @@ static bool child_state_change(private_medcli_listener_t *this, return TRUE; } -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_medcli_listener_t *this) +METHOD(medcli_listener_t, destroy, void, + private_medcli_listener_t *this) { this->db->execute(this->db, NULL, "UPDATE Connection SET Status = ?", DB_UINT, STATE_DOWN); @@ -116,15 +110,19 @@ static void destroy(private_medcli_listener_t *this) */ medcli_listener_t *medcli_listener_create(database_t *db) { - private_medcli_listener_t *this = malloc_thing(private_medcli_listener_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - - this->public.listener.ike_state_change = (void*)ike_state_change; - this->public.listener.child_state_change = (void*)child_state_change; - this->public.destroy = (void (*)(medcli_listener_t*))destroy; + private_medcli_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_state_change = _ike_state_change, + .child_state_change = _child_state_change, + }, + .destroy = _destroy, + }, + .db = db, + ); - this->db = db; db->execute(db, NULL, "UPDATE Connection SET Status = ?", DB_UINT, STATE_DOWN); diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index 068f311a5..91df95cf0 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -194,6 +194,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +205,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +222,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +272,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c index c23955ad0..6cacb34f6 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -52,29 +52,21 @@ struct private_medsrv_config_t { ike_cfg_t *ike; }; -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_medsrv_config_t *this, char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_medsrv_config_t *this, char *name) { return NULL; } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_medsrv_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_medsrv_config_t *this, host_t *me, host_t *other) { return enumerator_create_single(this->ike, NULL); } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_medsrv_config_t *this, identification_t *me, + identification_t *other) { enumerator_t *e; @@ -98,11 +90,11 @@ static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this, peer_cfg = peer_cfg_create( name, 2, this->ike->get_ref(this->ike), CERT_NEVER_SEND, UNIQUE_REPLACE, - 1, this->rekey*60, 0, /* keytries, rekey, reauth */ - this->rekey*5, this->rekey*3, /* jitter, overtime */ - TRUE, this->dpd, /* mobike, dpddelay */ - NULL, NULL, /* vip, pool */ - TRUE, NULL, NULL); /* mediation, med by, peer id */ + 1, this->rekey*60, 0, /* keytries, rekey, reauth */ + this->rekey*5, this->rekey*3, /* jitter, overtime */ + TRUE, this->dpd, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + TRUE, NULL, NULL); /* mediation, med by, peer id */ e->destroy(e); auth = auth_cfg_create(); @@ -121,10 +113,8 @@ static enumerator_t* create_peer_cfg_enumerator(private_medsrv_config_t *this, return NULL; } -/** - * Implementation of medsrv_config_t.destroy. - */ -static void destroy(private_medsrv_config_t *this) +METHOD(medsrv_config_t, destroy, void, + private_medsrv_config_t *this) { this->ike->destroy(this->ike); free(this); @@ -135,18 +125,23 @@ static void destroy(private_medsrv_config_t *this) */ medsrv_config_t *medsrv_config_create(database_t *db) { - private_medsrv_config_t *this = malloc_thing(private_medsrv_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.destroy = (void(*)(medsrv_config_t*))destroy; - - this->db = db; - this->rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200); - this->dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300); - this->ike = ike_cfg_create(FALSE, FALSE, - "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT); + private_medsrv_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .destroy = _destroy, + }, + .db = db, + .rekey = lib->settings->get_time(lib->settings, "medsrv.rekey", 1200), + .dpd = lib->settings->get_time(lib->settings, "medsrv.dpd", 300), + .ike = ike_cfg_create(FALSE, FALSE, + "0.0.0.0", IKEV2_UDP_PORT, "0.0.0.0", IKEV2_UDP_PORT), + ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); return &this->public; diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.c b/src/libcharon/plugins/medsrv/medsrv_creds.c index 8d1643908..3ae80f64c 100644 --- a/src/libcharon/plugins/medsrv/medsrv_creds.c +++ b/src/libcharon/plugins/medsrv/medsrv_creds.c @@ -51,11 +51,8 @@ typedef struct { key_type_t type; } cert_enumerator_t; -/** - * Implementation of cert_enumerator_t.public.enumerate - */ -static bool cert_enumerator_enumerate(cert_enumerator_t *this, - certificate_t **cert) +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) { certificate_t *trusted; public_key_t *public; @@ -91,22 +88,17 @@ static bool cert_enumerator_enumerate(cert_enumerator_t *this, return FALSE; } -/** - * Implementation of cert_enumerator_t.public.destroy - */ -static void cert_enumerator_destroy(cert_enumerator_t *this) +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) { DESTROY_IF(this->current); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of credential_set_t.create_cert_enumerator. - */ -static enumerator_t* create_cert_enumerator(private_medsrv_creds_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_medsrv_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) { cert_enumerator_t *e; @@ -116,15 +108,17 @@ static enumerator_t* create_cert_enumerator(private_medsrv_creds_t *this, return NULL; } - e = malloc_thing(cert_enumerator_t); - e->current = NULL; - e->type = key; - e->public.enumerate = (void*)cert_enumerator_enumerate; - e->public.destroy = (void*)cert_enumerator_destroy; - e->inner = this->db->query(this->db, - "SELECT public_key FROM peer WHERE keyid = ?", - DB_BLOB, id->get_encoding(id), - DB_BLOB); + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .type = key, + .inner = this->db->query(this->db, + "SELECT public_key FROM peer WHERE keyid = ?", + DB_BLOB, id->get_encoding(id), + DB_BLOB), + ); if (!e->inner) { free(e); @@ -133,10 +127,8 @@ static enumerator_t* create_cert_enumerator(private_medsrv_creds_t *this, return &e->public; } -/** - * Implementation of backend_t.destroy. - */ -static void destroy(private_medsrv_creds_t *this) +METHOD(medsrv_creds_t, destroy, void, + private_medsrv_creds_t *this) { free(this); } @@ -146,17 +138,21 @@ static void destroy(private_medsrv_creds_t *this) */ medsrv_creds_t *medsrv_creds_create(database_t *db) { - private_medsrv_creds_t *this = malloc_thing(private_medsrv_creds_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - - this->public.destroy = (void (*)(medsrv_creds_t*))destroy; - - this->db = db; + private_medsrv_creds_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .db = db, + ); return &this->public; } diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in index 308d27229..d9ad2388e 100644 --- a/src/libcharon/plugins/nm/Makefile.in +++ b/src/libcharon/plugins/nm/Makefile.in @@ -193,6 +193,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -201,6 +204,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -217,11 +221,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -265,6 +271,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/nm/nm_creds.c b/src/libcharon/plugins/nm/nm_creds.c index ea98c056d..f8fae9504 100644 --- a/src/libcharon/plugins/nm/nm_creds.c +++ b/src/libcharon/plugins/nm/nm_creds.c @@ -170,11 +170,13 @@ static bool cert_filter(cert_data_t *data, certificate_t **in, static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this, key_type_t key, identification_t *id) { - cert_data_t *data = malloc_thing(cert_data_t); + cert_data_t *data; - data->this = this; - data->id = id; - data->key = key; + INIT(data, + .this = this, + .id = id, + .key = key, + ); this->lock->read_lock(this->lock); return enumerator_create_filter( @@ -182,12 +184,9 @@ static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this, (void*)cert_filter, data, (void*)cert_data_destroy); } -/** - * Implements credential_set_t.create_cert_enumerator - */ -static enumerator_t* create_cert_enumerator(private_nm_creds_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_nm_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) { if (id && this->usercert && id->equals(id, this->usercert->get_subject(this->usercert))) @@ -201,11 +200,8 @@ static enumerator_t* create_cert_enumerator(private_nm_creds_t *this, return NULL; } -/** - * Implements credential_set_t.create_cert_enumerator - */ -static enumerator_t* create_private_enumerator(private_nm_creds_t *this, - key_type_t type, identification_t *id) +METHOD(credential_set_t, create_private_enumerator, enumerator_t*, + private_nm_creds_t *this, key_type_t type, identification_t *id) { if (this->key == NULL) { @@ -238,11 +234,9 @@ typedef struct { bool done; } shared_enumerator_t; -/** - * enumerate function for shared enumerator - */ -static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key, - id_match_t *me, id_match_t *other) +METHOD(enumerator_t, shared_enumerate, bool, + shared_enumerator_t *this, shared_key_t **key, id_match_t *me, + id_match_t *other) { if (this->done) { @@ -261,43 +255,41 @@ static bool shared_enumerate(shared_enumerator_t *this, shared_key_t **key, return TRUE; } -/** - * Destroy function for shared enumerator - */ -static void shared_destroy(shared_enumerator_t *this) +METHOD(enumerator_t, shared_destroy, void, + shared_enumerator_t *this) { this->key->destroy(this->key); this->this->lock->unlock(this->this->lock); free(this); } -/** - * Implements credential_set_t.create_cert_enumerator - */ -static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) + +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_nm_creds_t *this, shared_key_type_t type, identification_t *me, + identification_t *other) { shared_enumerator_t *enumerator; chunk_t key; + this->lock->read_lock(this->lock); + switch (type) { case SHARED_EAP: case SHARED_IKE: if (!this->pass || !this->user) { - return NULL; + goto no_secret; } if (me && !me->equals(me, this->user)) { - return NULL; + goto no_secret; } key = chunk_create(this->pass, strlen(this->pass)); break; case SHARED_PRIVATE_KEY_PASS: if (!this->keypass) { - return NULL; + goto no_secret; } key = chunk_create(this->keypass, strlen(this->keypass)); break; @@ -305,28 +297,31 @@ static enumerator_t* create_shared_enumerator(private_nm_creds_t *this, if (!this->keypass || !me || !chunk_equals(me->get_encoding(me), this->keyid)) { - return NULL; + goto no_secret; } key = chunk_create(this->keypass, strlen(this->keypass)); break; default: - return NULL; + goto no_secret; } - enumerator = malloc_thing(shared_enumerator_t); - enumerator->public.enumerate = (void*)shared_enumerate; - enumerator->public.destroy = (void*)shared_destroy; - enumerator->this = this; - enumerator->done = FALSE; - this->lock->read_lock(this->lock); + INIT(enumerator, + .public = { + .enumerate = (void*)_shared_enumerate, + .destroy = _shared_destroy, + }, + .this = this, + ); enumerator->key = shared_key_create(type, chunk_clone(key)); return &enumerator->public; + +no_secret: + this->lock->unlock(this->lock); + return NULL; } -/** - * Implementation of nm_creds_t.add_certificate - */ -static void add_certificate(private_nm_creds_t *this, certificate_t *cert) +METHOD(nm_creds_t, add_certificate, void, + private_nm_creds_t *this, certificate_t *cert) { this->lock->write_lock(this->lock); this->certs->insert_last(this->certs, cert); @@ -359,10 +354,8 @@ static void load_ca_file(private_nm_creds_t *this, char *file) } } -/** - * Implementation of nm_creds_t.load_ca_dir - */ -static void load_ca_dir(private_nm_creds_t *this, char *dir) +METHOD(nm_creds_t, load_ca_dir, void, + private_nm_creds_t *this, char *dir) { enumerator_t *enumerator; char *rel, *abs; @@ -390,11 +383,8 @@ static void load_ca_dir(private_nm_creds_t *this, char *dir) } } -/** - * Implementation of nm_creds_t.set_password - */ -static void set_username_password(private_nm_creds_t *this, identification_t *id, - char *password) +METHOD(nm_creds_t, set_username_password, void, + private_nm_creds_t *this, identification_t *id, char *password) { this->lock->write_lock(this->lock); DESTROY_IF(this->user); @@ -404,10 +394,8 @@ static void set_username_password(private_nm_creds_t *this, identification_t *id this->lock->unlock(this->lock); } -/** - * Implementation of nm_creds_t.set_key_password - */ -static void set_key_password(private_nm_creds_t *this, char *password) +METHOD(nm_creds_t, set_key_password, void, + private_nm_creds_t *this, char *password) { this->lock->write_lock(this->lock); free(this->keypass); @@ -415,10 +403,8 @@ static void set_key_password(private_nm_creds_t *this, char *password) this->lock->unlock(this->lock); } -/** - * Implementation of nm_creds_t.set_pin - */ -static void set_pin(private_nm_creds_t *this, chunk_t keyid, char *pin) +METHOD(nm_creds_t, set_pin, void, + private_nm_creds_t *this, chunk_t keyid, char *pin) { this->lock->write_lock(this->lock); free(this->keypass); @@ -428,11 +414,8 @@ static void set_pin(private_nm_creds_t *this, chunk_t keyid, char *pin) this->lock->unlock(this->lock); } -/** - * Implementation of nm_creds_t.set_cert_and_key - */ -static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, - private_key_t *key) +METHOD(nm_creds_t, set_cert_and_key, void, + private_nm_creds_t *this, certificate_t *cert, private_key_t *key) { this->lock->write_lock(this->lock); DESTROY_IF(this->key); @@ -442,10 +425,8 @@ static void set_cert_and_key(private_nm_creds_t *this, certificate_t *cert, this->lock->unlock(this->lock); } -/** - * Implementation of nm_creds_t.clear - */ -static void clear(private_nm_creds_t *this) +METHOD(nm_creds_t, clear, void, + private_nm_creds_t *this) { certificate_t *cert; @@ -467,10 +448,8 @@ static void clear(private_nm_creds_t *this) this->keyid = chunk_empty; } -/** - * Implementation of nm_creds_t.destroy - */ -static void destroy(private_nm_creds_t *this) +METHOD(nm_creds_t, destroy, void, + private_nm_creds_t *this) { clear(this); this->certs->destroy(this->certs); @@ -483,32 +462,29 @@ static void destroy(private_nm_creds_t *this) */ nm_creds_t *nm_creds_create() { - private_nm_creds_t *this = malloc_thing(private_nm_creds_t); - - this->public.set.create_private_enumerator = (void*)create_private_enumerator; - this->public.set.create_cert_enumerator = (void*)create_cert_enumerator; - this->public.set.create_shared_enumerator = (void*)create_shared_enumerator; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.add_certificate = (void(*)(nm_creds_t*, certificate_t *cert))add_certificate; - this->public.load_ca_dir = (void(*)(nm_creds_t*, char *dir))load_ca_dir; - this->public.set_username_password = (void(*)(nm_creds_t*, identification_t *id, char *password))set_username_password; - this->public.set_key_password = (void(*)(nm_creds_t*, char *password))set_key_password; - this->public.set_pin = (void(*)(nm_creds_t*, chunk_t keyid, char *pin))set_pin; - this->public.set_cert_and_key = (void(*)(nm_creds_t*, certificate_t *cert, private_key_t *key))set_cert_and_key; - this->public.clear = (void(*)(nm_creds_t*))clear; - this->public.destroy = (void(*)(nm_creds_t*))destroy; - - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - - this->certs = linked_list_create(); - this->user = NULL; - this->pass = NULL; - this->usercert = NULL; - this->key = NULL; - this->keypass = NULL; - this->keyid = chunk_empty; + private_nm_creds_t *this; + INIT(this, + .public = { + .set = { + .create_private_enumerator = _create_private_enumerator, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = _create_shared_enumerator, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .add_certificate = _add_certificate, + .load_ca_dir = _load_ca_dir, + .set_username_password = _set_username_password, + .set_key_password = _set_key_password, + .set_pin = _set_pin, + .set_cert_and_key = _set_cert_and_key, + .clear = _clear, + .destroy = _destroy, + }, + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .certs = linked_list_create(), + ); return &this->public; } diff --git a/src/libcharon/plugins/nm/nm_handler.c b/src/libcharon/plugins/nm/nm_handler.c index eacb54dda..408129ebe 100644 --- a/src/libcharon/plugins/nm/nm_handler.c +++ b/src/libcharon/plugins/nm/nm_handler.c @@ -40,11 +40,9 @@ struct private_nm_handler_t { linked_list_t *nbns; }; -/** - * Implementation of attribute_handler_t.handle - */ -static bool handle(private_nm_handler_t *this, identification_t *server, - configuration_attribute_type_t type, chunk_t data) +METHOD(attribute_handler_t, handle, bool, + private_nm_handler_t *this, identification_t *server, + configuration_attribute_type_t type, chunk_t data) { linked_list_t *list; @@ -93,11 +91,8 @@ static bool enumerate_dns(enumerator_t *this, return TRUE; } -/** - * Implementation of attribute_handler_t.create_attribute_enumerator - */ -static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this, - identification_t *server, host_t *vip) +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, + private_nm_handler_t *this, identification_t *server, host_t *vip) { if (vip && vip->get_family(vip) == AF_INET) { /* no IPv6 attributes yet */ @@ -120,11 +115,8 @@ static bool filter_chunks(void* null, char **in, chunk_t *out) return TRUE; } -/** - * Implementation of nm_handler_t.create_enumerator - */ -static enumerator_t* create_enumerator(private_nm_handler_t *this, - configuration_attribute_type_t type) +METHOD(nm_handler_t, create_enumerator, enumerator_t*, + private_nm_handler_t *this, configuration_attribute_type_t type) { linked_list_t *list; @@ -143,10 +135,8 @@ static enumerator_t* create_enumerator(private_nm_handler_t *this, (void*)filter_chunks, NULL, NULL); } -/** - * Implementation of nm_handler_t.reset - */ -static void reset(private_nm_handler_t *this) +METHOD(nm_handler_t, reset, void, + private_nm_handler_t *this) { void *data; @@ -160,10 +150,8 @@ static void reset(private_nm_handler_t *this) } } -/** - * Implementation of nm_handler_t.destroy. - */ -static void destroy(private_nm_handler_t *this) +METHOD(nm_handler_t, destroy, void, + private_nm_handler_t *this) { reset(this); this->dns->destroy(this->dns); @@ -176,17 +164,22 @@ static void destroy(private_nm_handler_t *this) */ nm_handler_t *nm_handler_create() { - private_nm_handler_t *this = malloc_thing(private_nm_handler_t); - - this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle; - this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop; - this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator; - this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator; - this->public.reset = (void(*)(nm_handler_t*))reset; - this->public.destroy = (void(*)(nm_handler_t*))destroy; - - this->dns = linked_list_create(); - this->nbns = linked_list_create(); + private_nm_handler_t *this; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = nop, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .create_enumerator = _create_enumerator, + .reset = _reset, + .destroy = _destroy, + }, + .dns = linked_list_create(), + .nbns = linked_list_create(), + ); return &this->public; } diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c index f1d3be7a5..84b7c810a 100644 --- a/src/libcharon/plugins/nm/nm_plugin.c +++ b/src/libcharon/plugins/nm/nm_plugin.c @@ -118,8 +118,8 @@ plugin_t *nm_plugin_create() }, .creds = nm_creds_create(), .handler = nm_handler_create(), - .plugin = nm_strongswan_plugin_new(this->creds, this->handler), ); + this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); lib->credmgr->add_set(lib->credmgr, &this->creds->set); @@ -134,7 +134,8 @@ plugin_t *nm_plugin_create() charon->keep_cap(charon, CAP_DAC_OVERRIDE); lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create((callback_job_cb_t)run, this, NULL, NULL)); + (job_t*)callback_job_create_with_prio((callback_job_cb_t)run, + this, NULL, NULL, JOB_PRIO_CRITICAL)); return &this->public.plugin; } diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index 4300b57cf..a6783fcc3 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -82,12 +82,11 @@ static void signal_ipv4_config(NMVPNPlugin *plugin, { GValue *val; GHashTable *config; - host_t *me, *other; + host_t *me; nm_handler_t *handler; config = g_hash_table_new(g_str_hash, g_str_equal); me = ike_sa->get_my_host(ike_sa); - other = ike_sa->get_other_host(ike_sa); handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin)->handler; /* NM requires a tundev, but netkey does not use one. Passing an invalid @@ -632,7 +631,8 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) u_int id; /* our ike_sa pointer might be invalid, lookup sa */ - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { if (priv->ike_sa == ike_sa) @@ -640,7 +640,7 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) id = ike_sa->get_unique_id(ike_sa); enumerator->destroy(enumerator); charon->controller->terminate_ike(charon->controller, id, - controller_cb_empty, NULL); + controller_cb_empty, NULL, 0); return TRUE; } } diff --git a/src/libcharon/plugins/nm/nm_service.h b/src/libcharon/plugins/nm/nm_service.h index b00000b6f..828d1a452 100644 --- a/src/libcharon/plugins/nm/nm_service.h +++ b/src/libcharon/plugins/nm/nm_service.h @@ -21,7 +21,7 @@ #ifndef NM_SERVICE_H_ #define NM_SERVICE_H_ -#include <glib/gtypes.h> +#include <glib.h> #include <glib-object.h> #include <nm-vpn-plugin.h> diff --git a/src/libcharon/plugins/radattr/Makefile.am b/src/libcharon/plugins/radattr/Makefile.am new file mode 100644 index 000000000..0ea8df5d1 --- /dev/null +++ b/src/libcharon/plugins/radattr/Makefile.am @@ -0,0 +1,17 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-radattr.la +else +libstrongswan_radattr_la_LIBADD = $(top_builddir)/src/libradius/libradius.la +plugin_LTLIBRARIES = libstrongswan-radattr.la +endif + +libstrongswan_radattr_la_SOURCES = radattr_plugin.h radattr_plugin.c \ + radattr_listener.h radattr_listener.c + +libstrongswan_radattr_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in new file mode 100644 index 000000000..ecea0df16 --- /dev/null +++ b/src/libcharon/plugins/radattr/Makefile.in @@ -0,0 +1,616 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/radattr +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +@MONOLITHIC_FALSE@libstrongswan_radattr_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libradius/libradius.la +am_libstrongswan_radattr_la_OBJECTS = radattr_plugin.lo \ + radattr_listener.lo +libstrongswan_radattr_la_OBJECTS = \ + $(am_libstrongswan_radattr_la_OBJECTS) +libstrongswan_radattr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_radattr_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_radattr_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_radattr_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_radattr_la_SOURCES) +DIST_SOURCES = $(libstrongswan_radattr_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-radattr.la +@MONOLITHIC_FALSE@libstrongswan_radattr_la_LIBADD = $(top_builddir)/src/libradius/libradius.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-radattr.la +libstrongswan_radattr_la_SOURCES = radattr_plugin.h radattr_plugin.c \ + radattr_listener.h radattr_listener.c + +libstrongswan_radattr_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/radattr/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/radattr/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-radattr.la: $(libstrongswan_radattr_la_OBJECTS) $(libstrongswan_radattr_la_DEPENDENCIES) + $(libstrongswan_radattr_la_LINK) $(am_libstrongswan_radattr_la_rpath) $(libstrongswan_radattr_la_OBJECTS) $(libstrongswan_radattr_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radattr_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radattr_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/radattr/radattr_listener.c b/src/libcharon/plugins/radattr/radattr_listener.c new file mode 100644 index 000000000..94b718a1b --- /dev/null +++ b/src/libcharon/plugins/radattr/radattr_listener.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "radattr_listener.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <errno.h> + +#include <daemon.h> + +#include <radius_message.h> + +/** + * Maximum size of an attribute to add + */ +#define MAX_ATTR_SIZE 1024 + +typedef struct private_radattr_listener_t private_radattr_listener_t; + +/** + * Private data of an radattr_listener_t object. + */ +struct private_radattr_listener_t { + + /** + * Public radattr_listener_t interface. + */ + radattr_listener_t public; + + /** + * Directory to look for attribute files + */ + char *dir; + + /** + * IKE_AUTH message ID to attribute + */ + int mid; +}; + +/** + * Print RADIUS attributes found in IKE message notifies + */ +static void print_radius_attributes(private_radattr_listener_t *this, + message_t *message) +{ + radius_attribute_type_t type; + enumerator_t *enumerator; + notify_payload_t *notify; + payload_t *payload; + chunk_t data; + + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == NOTIFY) + { + notify = (notify_payload_t*)payload; + if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE) + { + data = notify->get_notification_data(notify); + if (data.len >= 2) + { + type = data.ptr[0]; + data = chunk_skip(data, 2); + if (chunk_printable(data, NULL, 0)) + { + DBG1(DBG_IKE, "received RADIUS %N: %.*s", + radius_attribute_type_names, type, + (int)data.len, data.ptr); + } + else + { + DBG1(DBG_IKE, "received RADIUS %N: %#B", + radius_attribute_type_names, type, &data); + + } + } + } + } + } + enumerator->destroy(enumerator); +} + +/** + * Add a RADIUS attribute from a client-ID specific file to an IKE message + */ +static void add_radius_attribute(private_radattr_listener_t *this, + ike_sa_t *ike_sa, message_t *message) +{ + if (this->dir && + (this->mid == -1 || message->get_message_id(message) == this->mid)) + { + identification_t *id; + auth_cfg_t *auth; + char path[PATH_MAX]; + chunk_t data; + struct stat sb; + void *addr; + int fd; + + auth = ike_sa->get_auth_cfg(ike_sa, TRUE); + id = auth->get(auth, AUTH_RULE_EAP_IDENTITY); + if (!id) + { + id = ike_sa->get_my_id(ike_sa); + } + + snprintf(path, sizeof(path), "%s/%Y", this->dir, id); + fd = open(path, O_RDONLY); + if (fd != -1) + { + if (fstat(fd, &sb) != -1) + { + if (sb.st_size <= MAX_ATTR_SIZE) + { + addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr != MAP_FAILED) + { + data = chunk_create(addr, sb.st_size); + if (data.len >= 2) + { + DBG1(DBG_CFG, "adding RADIUS %N attribute", + radius_attribute_type_names, data.ptr[0]); + message->add_notify(message, FALSE, + RADIUS_ATTRIBUTE, data); + } + munmap(addr, sb.st_size); + } + else + { + DBG1(DBG_CFG, "mapping RADIUS attribute '%s' failed: %s", + path, strerror(errno)); + } + } + else + { + DBG1(DBG_CFG, "RADIUS attribute '%s' exceeds size limit", + path); + } + } + else + { + DBG1(DBG_CFG, "fstat RADIUS attribute '%s' failed: %s", + path, strerror(errno)); + } + close(fd); + } + else + { + DBG1(DBG_CFG, "reading RADIUS attribute '%s' failed: %s", + path, strerror(errno)); + } + } +} + +METHOD(listener_t, message, bool, + private_radattr_listener_t *this, + ike_sa_t *ike_sa, message_t *message, bool incoming) +{ + if (ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) && + message->get_exchange_type(message) == IKE_AUTH && + message->get_payload(message, EXTENSIBLE_AUTHENTICATION)) + { + if (incoming) + { + print_radius_attributes(this, message); + } + else + { + add_radius_attribute(this, ike_sa, message); + } + } + return TRUE; +} + + +METHOD(radattr_listener_t, destroy, void, + private_radattr_listener_t *this) +{ + free(this); +} + +/** + * See header + */ +radattr_listener_t *radattr_listener_create() +{ + private_radattr_listener_t *this; + + INIT(this, + .public = { + .listener = { + .message = _message, + }, + .destroy = _destroy, + }, + .dir = lib->settings->get_str(lib->settings, + "charon.plugins.radattr.dir", NULL), + .mid = lib->settings->get_int(lib->settings, + "charon.plugins.radattr.message_id", -1), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/radattr/radattr_listener.h b/src/libcharon/plugins/radattr/radattr_listener.h new file mode 100644 index 000000000..e61c441bf --- /dev/null +++ b/src/libcharon/plugins/radattr/radattr_listener.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 radattr_listener radattr_listener + * @{ @ingroup radattr + */ + +#ifndef RADATTR_LISTENER_H_ +#define RADATTR_LISTENER_H_ + +#include <bus/listeners/listener.h> + +typedef struct radattr_listener_t radattr_listener_t; + +/** + * Output received RADIUS attributes, inject custom attributes. + */ +struct radattr_listener_t { + + /** + * Implements a listener. + */ + listener_t listener; + + /** + * Destroy a radattr_listener_t. + */ + void (*destroy)(radattr_listener_t *this); +}; + +/** + * Create a radattr_listener instance. + */ +radattr_listener_t *radattr_listener_create(); + +#endif /** RADATTR_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/radattr/radattr_plugin.c b/src/libcharon/plugins/radattr/radattr_plugin.c new file mode 100644 index 000000000..85ea326ac --- /dev/null +++ b/src/libcharon/plugins/radattr/radattr_plugin.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 "radattr_plugin.h" + +#include "radattr_listener.h" + +#include <daemon.h> + +typedef struct private_radattr_plugin_t private_radattr_plugin_t; + +/** + * private data of radattr plugin + */ +struct private_radattr_plugin_t { + + /** + * implements plugin interface + */ + radattr_plugin_t public; + + /** + * Listener acting on messages + */ + radattr_listener_t *listener; +}; + +METHOD(plugin_t, get_name, char*, + private_radattr_plugin_t *this) +{ + return "radattr"; +} + +METHOD(plugin_t, destroy, void, + private_radattr_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *radattr_plugin_create() +{ + private_radattr_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .listener = radattr_listener_create(), + ); + + charon->bus->add_listener(charon->bus, &this->listener->listener); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/radattr/radattr_plugin.h b/src/libcharon/plugins/radattr/radattr_plugin.h new file mode 100644 index 000000000..c3bad5a3a --- /dev/null +++ b/src/libcharon/plugins/radattr/radattr_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 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 radattr radattr + * @ingroup cplugins + * + * @defgroup radattr_plugin radattr_plugin + * @{ @ingroup radattr + */ + +#ifndef RADATTR_PLUGIN_H_ +#define RADATTR_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct radattr_plugin_t radattr_plugin_t; + +/** + * Plugin to inject/process custom RADIUS attributes. + */ +struct radattr_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** RADATTR_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index e36fa6bb4..59a560b86 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,6 +203,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -216,11 +220,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index d20f32248..2b830012d 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -208,12 +208,13 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer /* <ikesalist> */ xmlTextWriterStartElement(writer, "ikesalist"); - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { ike_sa_id_t *id; host_t *local, *remote; - iterator_t *children; + enumerator_t *children; child_sa_t *child_sa; id = ike_sa->get_id(ike_sa); @@ -263,8 +264,8 @@ static void request_query_ikesa(xmlTextReaderPtr reader, xmlTextWriterPtr writer /* <childsalist> */ xmlTextWriterStartElement(writer, "childsalist"); - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, (void**)&child_sa)) { write_child(writer, child_sa); } @@ -394,7 +395,8 @@ static void request_control_terminate(xmlTextReaderPtr reader, enumerator_t *enumerator; ike_sa_t *ike_sa; - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { if (streq(str, ike_sa->get_name(ike_sa))) @@ -419,14 +421,14 @@ static void request_control_terminate(xmlTextReaderPtr reader, if (ike) { status = charon->controller->terminate_ike( - charon->controller, id, - (controller_cb_t)xml_callback, writer); + charon->controller, id, + (controller_cb_t)xml_callback, writer, 0); } else { status = charon->controller->terminate_child( - charon->controller, id, - (controller_cb_t)xml_callback, writer); + charon->controller, id, + (controller_cb_t)xml_callback, writer, 0); } /* </log> */ xmlTextWriterEndElement(writer); @@ -459,17 +461,21 @@ static void request_control_initiate(xmlTextReaderPtr reader, /* <log> */ xmlTextWriterStartElement(writer, "log"); - peer = charon->backends->get_peer_cfg_by_name(charon->backends, (char*)str); + peer = charon->backends->get_peer_cfg_by_name(charon->backends, + (char*)str); if (peer) { enumerator = peer->create_child_cfg_enumerator(peer); if (ike) { - if (!enumerator->enumerate(enumerator, &child)) + if (enumerator->enumerate(enumerator, &child)) + { + child->get_ref(child); + } + else { child = NULL; } - child->get_ref(child); } else { @@ -488,7 +494,7 @@ static void request_control_initiate(xmlTextReaderPtr reader, { status = charon->controller->initiate(charon->controller, peer, child, (controller_cb_t)xml_callback, - writer); + writer, 0); } else { @@ -625,7 +631,7 @@ static job_requeue_t process(int *fdp) int fd = *fdp; bool oldstate; char buffer[4096]; - size_t len; + ssize_t len; xmlTextReaderPtr reader; char *id = NULL, *type = NULL; @@ -640,7 +646,7 @@ static job_requeue_t process(int *fdp) DBG2(DBG_CFG, "SMP XML connection closed"); return JOB_REQUEUE_NONE; } - DBG3(DBG_CFG, "got XML request: %b", buffer, len); + DBG3(DBG_CFG, "got XML request: %b", buffer, (u_int)len); reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0); if (reader == NULL) @@ -772,7 +778,8 @@ plugin_t *smp_plugin_create() return NULL; } - this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); + this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch, + this, NULL, NULL, JOB_PRIO_CRITICAL); lib->processor->queue_job(lib->processor, (job_t*)this->job); return &this->public.plugin; diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index 95cb04d14..9c4e5e7b4 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.c b/src/libcharon/plugins/socket_default/socket_default_plugin.c index 1bc8244d5..01d9473bf 100644 --- a/src/libcharon/plugins/socket_default/socket_default_plugin.c +++ b/src/libcharon/plugins/socket_default/socket_default_plugin.c @@ -43,11 +43,20 @@ METHOD(plugin_t, get_name, char*, METHOD(plugin_t, destroy, void, private_socket_default_plugin_t *this) { - charon->socket->remove_socket(charon->socket, - (socket_constructor_t)socket_default_socket_create); free(this); } +METHOD(plugin_t, get_features, int, + private_socket_default_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(socket_register, socket_default_socket_create), + PLUGIN_PROVIDE(CUSTOM, "socket"), + }; + *features = f; + return countof(f); +} + /* * see header file */ @@ -59,15 +68,11 @@ plugin_t *socket_default_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - charon->socket->add_socket(charon->socket, - (socket_constructor_t)socket_default_socket_create); - return &this->public.plugin; } - diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index e95646643..76ca1df42 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -461,15 +461,15 @@ static int open_socket(private_socket_default_socket_t *this, 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; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = INADDR_ANY; - sin->sin_port = htons(port); + htoun32(&sin->sin_addr.s_addr, INADDR_ANY); + htoun16(&sin->sin_port, port); addrlen = sizeof(struct sockaddr_in); sol = SOL_IP; #ifdef IP_PKTINFO @@ -482,9 +482,8 @@ static int open_socket(private_socket_default_socket_t *this, case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; - sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); - sin6->sin6_port = htons(port); + htoun16(&sin6->sin6_port, port); addrlen = sizeof(struct sockaddr_in6); sol = SOL_IPV6; pktinfo = IPV6_RECVPKTINFO; diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 97e3a713d..f45e3d255 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c index c5ea37a10..c21d5240e 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c @@ -34,6 +34,17 @@ struct private_socket_dynamic_plugin_t { socket_dynamic_plugin_t public; }; +METHOD(plugin_t, get_features, int, + private_socket_dynamic_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(socket_register, socket_dynamic_socket_create), + PLUGIN_PROVIDE(CUSTOM, "socket"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, get_name, char*, private_socket_dynamic_plugin_t *this) { @@ -43,8 +54,6 @@ METHOD(plugin_t, get_name, char*, METHOD(plugin_t, destroy, void, private_socket_dynamic_plugin_t *this) { - charon->socket->remove_socket(charon->socket, - (socket_constructor_t)socket_dynamic_socket_create); free(this); } @@ -59,15 +68,12 @@ plugin_t *socket_dynamic_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - charon->socket->add_socket(charon->socket, - (socket_constructor_t)socket_dynamic_socket_create); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index 74dba82cc..eee3814a8 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -235,7 +235,7 @@ static packet_t *receive_packet(private_socket_dynamic_socket_t *this, DBG1(DBG_NET, "receive buffer too small, packet discarded"); return NULL; } - DBG3(DBG_NET, "received packet %b", buffer, len); + DBG3(DBG_NET, "received packet %b", buffer, (u_int)len); if (len < MARKER_LEN) { diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in index 6f1a09c88..5abceb6c3 100644 --- a/src/libcharon/plugins/socket_raw/Makefile.in +++ b/src/libcharon/plugins/socket_raw/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c index 5bd28bd42..1299c30ca 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c @@ -40,11 +40,20 @@ METHOD(plugin_t, get_name, char*, return "socket-raw"; } +METHOD(plugin_t, get_features, int, + private_socket_raw_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(socket_register, socket_raw_socket_create), + PLUGIN_PROVIDE(CUSTOM, "socket"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, private_socket_raw_plugin_t *this) { - charon->socket->remove_socket(charon->socket, - (socket_constructor_t)socket_raw_socket_create); free(this); } @@ -59,15 +68,12 @@ plugin_t *socket_raw_plugin_create() .public = { .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, }, ); - charon->socket->add_socket(charon->socket, - (socket_constructor_t)socket_raw_socket_create); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index f6e87a86f..ae37d8f2b 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -31,7 +31,6 @@ #include <sys/ioctl.h> #include <netinet/in.h> #include <netinet/ip.h> -#include <netinet/ip6.h> #include <netinet/udp.h> #include <linux/types.h> #include <linux/filter.h> @@ -259,6 +258,8 @@ METHOD(socket_t, receiver, status_t, DBG1(DBG_NET, "error reading IPv6 ancillary data"); return FAILED; } + +#ifdef HAVE_IN6_PKTINFO if (cmsgptr->cmsg_level == SOL_IPV6 && cmsgptr->cmsg_type == IPV6_2292PKTINFO) { @@ -273,6 +274,7 @@ METHOD(socket_t, receiver, status_t, src.sin6_port = udp->source; dest = host_create_from_sockaddr((sockaddr_t*)&dst); } +#endif /* HAVE_IN6_PKTINFO */ } /* ancillary data missing? */ if (dest == NULL) @@ -397,6 +399,7 @@ METHOD(socket_t, sender, status_t, sin = (struct sockaddr_in*)src->get_sockaddr(src); memcpy(&pktinfo->ipi_spec_dst, &sin->sin_addr, sizeof(struct in_addr)); } +#ifdef HAVE_IN6_PKTINFO else { char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; @@ -414,6 +417,7 @@ METHOD(socket_t, sender, status_t, sin = (struct sockaddr_in6*)src->get_sockaddr(src); memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr)); } +#endif /* HAVE_IN6_PKTINFO */ } bytes_sent = sendmsg(skt, &msg, 0); @@ -435,29 +439,25 @@ static int open_send_socket(private_socket_raw_socket_t *this, int on = TRUE; int type = UDP_ENCAP_ESPINUDP; struct sockaddr_storage addr; - u_int sol; 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; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = INADDR_ANY; - sin->sin_port = htons(port); - sol = SOL_IP; + htoun32(&sin->sin_addr.s_addr, INADDR_ANY); + htoun16(&sin->sin_port, port); break; } case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; - sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); - sin6->sin6_port = htons(port); - sol = SOL_IPV6; + htoun16(&sin6->sin6_port, port); break; } default: @@ -514,18 +514,16 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) { int skt; int on = TRUE; - u_int proto_offset, ip_len, sol, udp_header, ike_header; + u_int ip_len, sol, udp_header, ike_header; /* precalculate constants depending on address family */ switch (family) { case AF_INET: - proto_offset = IP_PROTO_OFFSET; ip_len = IP_LEN; sol = SOL_IP; break; case AF_INET6: - proto_offset = IP6_PROTO_OFFSET; ip_len = 0; /* IPv6 raw sockets contain no IP header */ sol = SOL_IPV6; break; diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index d7b43dcc9..d04c7f6c9 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,6 +203,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -216,11 +220,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/sql/sql_logger.c b/src/libcharon/plugins/sql/sql_logger.c index d350c4c3d..10ceacb00 100644 --- a/src/libcharon/plugins/sql/sql_logger.c +++ b/src/libcharon/plugins/sql/sql_logger.c @@ -47,11 +47,9 @@ struct private_sql_logger_t { bool recursive; }; -/** - * Implementation of bus_listener_t.log. - */ -static bool log_(private_sql_logger_t *this, debug_t group, level_t level, - int thread, ike_sa_t* ike_sa, char *format, va_list args) +METHOD(listener_t, log_, bool, + private_sql_logger_t *this, debug_t group, level_t level, int thread, + ike_sa_t* ike_sa, char *format, va_list args) { if (this->recursive) { @@ -115,10 +113,8 @@ static bool log_(private_sql_logger_t *this, debug_t group, level_t level, return TRUE; } -/** - * Implementation of sql_logger_t.destroy. - */ -static void destroy(private_sql_logger_t *this) +METHOD(sql_logger_t, destroy, void, + private_sql_logger_t *this) { free(this); } @@ -128,17 +124,19 @@ static void destroy(private_sql_logger_t *this) */ sql_logger_t *sql_logger_create(database_t *db) { - private_sql_logger_t *this = malloc_thing(private_sql_logger_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_; - this->public.destroy = (void(*)(sql_logger_t*))destroy; - - this->db = db; - this->recursive = FALSE; - - this->level = lib->settings->get_int(lib->settings, - "charon.plugins.sql.loglevel", -1); + private_sql_logger_t *this; + + INIT(this, + .public = { + .listener = { + .log = _log_, + }, + .destroy = _destroy, + }, + .db = db, + .level = lib->settings->get_int(lib->settings, + "charon.plugins.sql.loglevel", -1), + ); return &this->public; } diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index fd859daeb..60f5f535a 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -195,6 +195,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +206,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +223,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +273,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c index 69e13deb9..bec35a661 100644 --- a/src/libcharon/plugins/stroke/stroke_ca.c +++ b/src/libcharon/plugins/stroke/stroke_ca.c @@ -319,7 +319,7 @@ static void list_uris(linked_list_t *list, char *label, FILE *out) { if (first) { - fprintf(out, label); + fprintf(out, "%s", label); first = FALSE; } else diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 2b3164384..483e3d253 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -263,7 +264,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, { identification_t *identity; certificate_t *certificate; - char *auth, *id, *cert, *ca; + char *auth, *id, *pubkey, *cert, *ca; stroke_end_t *end, *other_end; auth_cfg_t *cfg; char eap_buf[32]; @@ -328,6 +329,9 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, case AUTH_CLASS_EAP: auth = "eap"; break; + case AUTH_CLASS_ANY: + auth = "any"; + break; } } else @@ -396,6 +400,18 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } cfg->add(cfg, AUTH_RULE_IDENTITY, identity); + /* add raw RSA public key */ + pubkey = end->rsakey; + if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert")) + { + certificate = this->cred->load_pubkey(this->cred, KEY_RSA, pubkey, + identity); + if (certificate) + { + cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate); + } + } + /* CA constraint */ if (ca) { @@ -775,13 +791,28 @@ static void add_ts(private_stroke_config_t *this, } /** + * map starter magic values to our action type + */ +static action_t map_action(int starter_action) +{ + switch (starter_action) + { + case 2: /* =hold */ + return ACTION_ROUTE; + case 3: /* =restart */ + return ACTION_RESTART; + default: + return ACTION_NONE; + } +} + +/** * build a child config from the stroke message */ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, stroke_msg_t *msg) { child_cfg_t *child_cfg; - action_t dpd; lifetime_cfg_t lifetime = { .time = { .life = msg->add_conn.rekey.ipsec_lifetime, @@ -808,23 +839,11 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, .mask = msg->add_conn.mark_out.mask }; - switch (msg->add_conn.dpd.action) - { /* map startes magic values to our action type */ - case 2: /* =hold */ - dpd = ACTION_ROUTE; - break; - case 3: /* =restart */ - dpd = ACTION_RESTART; - break; - default: - dpd = ACTION_NONE; - break; - } - child_cfg = child_cfg_create( - msg->add_conn.name, &lifetime, - msg->add_conn.me.updown, msg->add_conn.me.hostaccess, - msg->add_conn.mode, ACTION_NONE, dpd, dpd, msg->add_conn.ipcomp, + msg->add_conn.name, &lifetime, msg->add_conn.me.updown, + msg->add_conn.me.hostaccess, msg->add_conn.mode, ACTION_NONE, + map_action(msg->add_conn.dpd.action), + map_action(msg->add_conn.close_action), msg->add_conn.ipcomp, msg->add_conn.inactivity, msg->add_conn.reqid, &mark_in, &mark_out, msg->add_conn.tfc); child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode, @@ -950,6 +969,175 @@ METHOD(stroke_config_t, del, void, } } +METHOD(stroke_config_t, set_user_credentials, void, + private_stroke_config_t *this, stroke_msg_t *msg, FILE *prompt) +{ + enumerator_t *enumerator, *children, *remote_auth; + peer_cfg_t *peer, *found = NULL; + auth_cfg_t *auth_cfg, *remote_cfg; + auth_class_t auth_class; + child_cfg_t *child; + identification_t *id, *identity, *gw = NULL; + shared_key_type_t type = SHARED_ANY; + chunk_t password = chunk_empty; + + this->mutex->lock(this->mutex); + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, (void**)&peer)) + { /* find the peer (or child) config with the given name */ + if (streq(peer->get_name(peer), msg->user_creds.name)) + { + found = peer; + } + else + { + children = peer->create_child_cfg_enumerator(peer); + while (children->enumerate(children, &child)) + { + if (streq(child->get_name(child), msg->user_creds.name)) + { + found = peer; + break; + } + } + children->destroy(children); + } + + if (found) + { + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + DBG1(DBG_CFG, " no config named '%s'", msg->user_creds.name); + fprintf(prompt, "no config named '%s'\n", msg->user_creds.name); + this->mutex->unlock(this->mutex); + return; + } + + id = identification_create_from_string(msg->user_creds.username); + if (strlen(msg->user_creds.username) == 0 || + !id || id->get_type(id) == ID_ANY) + { + DBG1(DBG_CFG, " invalid username '%s'", msg->user_creds.username); + fprintf(prompt, "invalid username '%s'\n", msg->user_creds.username); + this->mutex->unlock(this->mutex); + DESTROY_IF(id); + return; + } + + /* replace/set the username in the first EAP auth_cfg, also look for a + * suitable remote ID. + * note that adding the identity here is not fully thread-safe as the + * peer_cfg and in turn the auth_cfg could be in use. for the default use + * case (setting user credentials before upping the connection) this will + * not be a problem, though. */ + enumerator = found->create_auth_cfg_enumerator(found, TRUE); + remote_auth = found->create_auth_cfg_enumerator(found, FALSE); + while (enumerator->enumerate(enumerator, (void**)&auth_cfg)) + { + if (remote_auth->enumerate(remote_auth, (void**)&remote_cfg)) + { /* fall back on rightid, in case aaa_identity is not specified */ + identity = remote_cfg->get(remote_cfg, AUTH_RULE_IDENTITY); + if (identity && identity->get_type(identity) != ID_ANY) + { + gw = identity; + } + } + + auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS); + if (auth_class == AUTH_CLASS_EAP) + { + auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id)); + /* if aaa_identity is specified use that as remote ID */ + identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY); + if (identity && identity->get_type(identity) != ID_ANY) + { + gw = identity; + } + DBG1(DBG_CFG, " configured EAP-Identity %Y", id); + type = SHARED_EAP; + break; + } + } + enumerator->destroy(enumerator); + remote_auth->destroy(remote_auth); + /* clone the gw ID before unlocking the mutex */ + if (gw) + { + gw = gw->clone(gw); + } + this->mutex->unlock(this->mutex); + + if (type == SHARED_ANY) + { + DBG1(DBG_CFG, " config '%s' unsuitable for user credentials", + msg->user_creds.name); + fprintf(prompt, "config '%s' unsuitable for user credentials\n", + msg->user_creds.name); + id->destroy(id); + DESTROY_IF(gw); + return; + } + + if (msg->user_creds.password) + { + char *pass; + + pass = msg->user_creds.password; + password = chunk_clone(chunk_create(pass, strlen(pass))); + memwipe(pass, strlen(pass)); + } + else + { /* prompt the user for the password */ + char buf[256]; + + fprintf(prompt, "Password:\n"); + if (fgets(buf, sizeof(buf), prompt)) + { + password = chunk_clone(chunk_create(buf, strlen(buf))); + if (password.len > 0) + { /* trim trailing \n */ + password.len--; + } + memwipe(buf, sizeof(buf)); + } + } + + if (password.len) + { + shared_key_t *shared; + linked_list_t *owners; + + shared = shared_key_create(type, password); + + owners = linked_list_create(); + owners->insert_last(owners, id->clone(id)); + if (gw && gw->get_type(gw) != ID_ANY) + { + owners->insert_last(owners, gw->clone(gw)); + DBG1(DBG_CFG, " added %N secret for %Y %Y", shared_key_type_names, + type, id, gw); + } + else + { + DBG1(DBG_CFG, " added %N secret for %Y", shared_key_type_names, + type, id); + } + this->cred->add_shared(this->cred, shared, owners); + DBG4(DBG_CFG, " secret: %#B", &password); + } + else + { /* in case a user answers the password prompt by just pressing enter */ + chunk_clear(&password); + } + id->destroy(id); + DESTROY_IF(gw); +} + METHOD(stroke_config_t, destroy, void, private_stroke_config_t *this) { @@ -974,6 +1162,7 @@ stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred) }, .add = _add, .del = _del, + .set_user_credentials = _set_user_credentials, .destroy = _destroy, }, .list = linked_list_create(), diff --git a/src/libcharon/plugins/stroke/stroke_config.h b/src/libcharon/plugins/stroke/stroke_config.h index 05e4665ca..450d517f3 100644 --- a/src/libcharon/plugins/stroke/stroke_config.h +++ b/src/libcharon/plugins/stroke/stroke_config.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -53,6 +54,15 @@ struct stroke_config_t { void (*del)(stroke_config_t *this, stroke_msg_t *msg); /** + * Set the username and password for a connection in this backend. + * + * @param msg received stroke message + * @param prompt I/O channel to prompt for the password + */ + void (*set_user_credentials)(stroke_config_t *this, stroke_msg_t *msg, + FILE *prompt); + + /** * Destroy a stroke_config instance. */ void (*destroy)(stroke_config_t *this); diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index 4943ee670..729e9d757 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -15,7 +15,9 @@ #include "stroke_control.h" +#include <hydra.h> #include <daemon.h> + #include <processing/jobs/delete_ike_sa_job.h> #include <processing/jobs/rekey_ike_sa_job.h> #include <processing/jobs/rekey_child_sa_job.h> @@ -101,14 +103,14 @@ static void charon_initiate(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, if (msg->output_verbosity < 0) { charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - NULL, NULL); + NULL, NULL, 0); } else { stroke_log_info_t info = { msg->output_verbosity, out }; charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } } @@ -275,28 +277,29 @@ METHOD(stroke_control_t, terminate, void, if (child) { charon->controller->terminate_child(charon->controller, id, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } else { charon->controller->terminate_ike(charon->controller, id, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } return; } ike_list = linked_list_create(); child_list = linked_list_create(); - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { child_sa_t *child_sa; - iterator_t *children; + enumerator_t *children; if (child) { - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, (void**)&child_sa)) { if (streq(name, child_sa->get_name(child_sa))) { @@ -330,7 +333,7 @@ METHOD(stroke_control_t, terminate, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_child(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); @@ -338,7 +341,7 @@ METHOD(stroke_control_t, terminate, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_ike(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); @@ -366,16 +369,17 @@ METHOD(stroke_control_t, rekey, void, DBG1(DBG_CFG, "error parsing specifier string"); return; } - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { child_sa_t *child_sa; - iterator_t *children; + enumerator_t *children; if (child) { - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, (void**)&child_sa)) { if ((name && streq(name, child_sa->get_name(child_sa))) || (id && id == child_sa->get_reqid(child_sa))) @@ -442,7 +446,8 @@ METHOD(stroke_control_t, terminate_srcip, void, chunk_end = end->get_address(end); } - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { vip = ike_sa->get_virtual_ip(ike_sa, FALSE); @@ -481,8 +486,7 @@ METHOD(stroke_control_t, terminate_srcip, void, METHOD(stroke_control_t, purge_ike, void, private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { - enumerator_t *enumerator; - iterator_t *iterator; + enumerator_t *enumerator, *children; ike_sa_t *ike_sa; child_sa_t *child_sa; linked_list_t *list; @@ -493,16 +497,17 @@ METHOD(stroke_control_t, purge_ike, void, info.level = msg->output_verbosity; list = linked_list_create(); - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { - iterator = ike_sa->create_child_sa_iterator(ike_sa); - if (!iterator->iterate(iterator, (void**)&child_sa)) + children = ike_sa->create_child_sa_enumerator(ike_sa); + if (!children->enumerate(children, (void**)&child_sa)) { list->insert_last(list, (void*)(uintptr_t)ike_sa->get_unique_id(ike_sa)); } - iterator->destroy(iterator); + children->destroy(children); } enumerator->destroy(enumerator); @@ -510,25 +515,44 @@ METHOD(stroke_control_t, purge_ike, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_ike(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); list->destroy(list); } /** - * call charon to install a trap + * call charon to install a shunt or trap */ static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, char *name, FILE *out) { - if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) + ipsec_mode_t mode; + + mode = child_cfg->get_mode(child_cfg); + if (mode == MODE_PASS || mode == MODE_DROP) { - fprintf(out, "'%s' routed\n", name); + if (charon->shunts->install(charon->shunts, child_cfg)) + { + fprintf(out, "'%s' shunt %N policy installed\n", + name, ipsec_mode_names, mode); + } + else + { + fprintf(out, "'%s' shunt %N policy installation failed\n", + name, ipsec_mode_names, mode); + } } else { - fprintf(out, "routing '%s' failed\n", name); + if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) + { + fprintf(out, "'%s' routed\n", name); + } + else + { + fprintf(out, "routing '%s' failed\n", name); + } } } @@ -609,7 +633,13 @@ METHOD(stroke_control_t, unroute, void, { child_sa_t *child_sa; enumerator_t *enumerator; - u_int32_t id; + u_int32_t id = 0; + + if (charon->shunts->uninstall(charon->shunts, msg->unroute.name)) + { + fprintf(out, "shunt policy '%s' uninstalled\n", msg->unroute.name); + return; + } enumerator = charon->traps->create_enumerator(charon->traps); while (enumerator->enumerate(enumerator, NULL, &child_sa)) @@ -617,14 +647,20 @@ METHOD(stroke_control_t, unroute, void, if (streq(msg->unroute.name, child_sa->get_name(child_sa))) { id = child_sa->get_reqid(child_sa); - enumerator->destroy(enumerator); - charon->traps->uninstall(charon->traps, id); - fprintf(out, "configuration '%s' unrouted\n", msg->unroute.name); - return; + break; } } enumerator->destroy(enumerator); - fprintf(out, "configuration '%s' not found\n", msg->unroute.name); + + if (id) + { + charon->traps->uninstall(charon->traps, id); + fprintf(out, "configuration '%s' unrouted\n", msg->unroute.name); + } + else + { + fprintf(out, "configuration '%s' not found\n", msg->unroute.name); + } } METHOD(stroke_control_t, destroy, void, diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index baf02a6da..a2a6d6d9f 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2010 Tobias Brunner + * Copyright (C) 2008-2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -17,13 +17,16 @@ #include <sys/types.h> #include <sys/stat.h> #include <limits.h> -#include <glob.h> #include <libgen.h> #include <sys/mman.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif + #include "stroke_cred.h" #include <credentials/certificates/x509.h> @@ -68,15 +71,19 @@ struct private_stroke_cred_t { mem_cred_t *creds; /** + * ignore missing CA basic constraint (i.e. treat all certificates in + * ipsec.conf ca sections and ipsec.d/cacert as CA certificates) + */ + bool force_ca_cert; + + /** * cache CRLs to disk? */ bool cachecrl; }; -/** - * Implementation of stroke_cred_t.load_ca. - */ -static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) +METHOD(stroke_cred_t, load_ca, certificate_t*, + private_stroke_cred_t *this, char *filename) { certificate_t *cert; char path[PATH_MAX]; @@ -90,10 +97,21 @@ static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename); } - cert = lib->creds->create(lib->creds, + if (this->force_ca_cert) + { /* we treat this certificate as a CA certificate even if it has no + * CA basic constraint */ + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, path, BUILD_X509_FLAG, X509_CA, + BUILD_END); + } + else + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, path, BUILD_END); + } if (cert) { x509_t *x509 = (x509_t*)cert; @@ -110,10 +128,8 @@ static certificate_t* load_ca(private_stroke_cred_t *this, char *filename) return NULL; } -/** - * Implementation of stroke_cred_t.load_peer. - */ -static certificate_t* load_peer(private_stroke_cred_t *this, char *filename) +METHOD(stroke_cred_t, load_peer, certificate_t*, + private_stroke_cred_t *this, char *filename) { certificate_t *cert; char path[PATH_MAX]; @@ -142,6 +158,78 @@ static certificate_t* load_peer(private_stroke_cred_t *this, char *filename) return NULL; } +METHOD(stroke_cred_t, load_pubkey, certificate_t*, + private_stroke_cred_t *this, key_type_t type, char *filename, + identification_t *identity) +{ + certificate_t *cert; + char path[PATH_MAX]; + + if (streq(filename, "%dns")) + { + + } + else if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) + { + chunk_t printable_key, rfc3110_key; + public_key_t *key; + + printable_key = chunk_create(filename + 2, strlen(filename) - 2); + rfc3110_key = strncaseeq(filename, "0x", 2) ? + chunk_from_hex(printable_key, NULL) : + chunk_from_base64(printable_key, NULL); + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_DNSKEY, rfc3110_key, + BUILD_END); + free(rfc3110_key.ptr); + if (key) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_TRUSTED_PUBKEY, + BUILD_PUBLIC_KEY, key, + BUILD_SUBJECT, identity, + BUILD_END); + key->destroy(key); + if (cert) + { + cert = this->creds->add_cert_ref(this->creds, TRUE, cert); + DBG1(DBG_CFG, " loaded %N public key for \"%Y\"", + key_type_names, type, identity); + return cert; + } + } + DBG1(DBG_CFG, " loading %N public key for \"%Y\" failed", + key_type_names, type, identity); + } + else + { + if (*filename == '/') + { + snprintf(path, sizeof(path), "%s", filename); + } + else + { + snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); + } + + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, + BUILD_FROM_FILE, path, + BUILD_SUBJECT, identity, + BUILD_END); + if (cert) + { + cert = this->creds->add_cert_ref(this->creds, TRUE, cert); + DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'", + key_type_names, type, identity, filename); + return cert; + } + DBG1(DBG_CFG, " loading %N public key for \"%Y\" from '%s' failed", + key_type_names, type, identity, filename); + } + return NULL; +} + /** * load trusted certificates from a directory */ @@ -172,11 +260,21 @@ static void load_certdir(private_stroke_cred_t *this, char *path, { case CERT_X509: if (flag & X509_CA) - { /* for CA certificates, we strictly require - * the CA basic constraint to be set */ - cert = lib->creds->create(lib->creds, + { + if (this->force_ca_cert) + { /* treat this certificate as CA cert even it has no + * CA basic constraint */ + cert = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_X509_FLAG, + X509_CA, BUILD_END); + } + else + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, file, BUILD_END); + } if (cert) { x509_t *x509 = (x509_t*)cert; @@ -262,10 +360,8 @@ static void load_certdir(private_stroke_cred_t *this, char *path, enumerator->destroy(enumerator); } -/** - * Implementation of credential_set_t.cache_cert. - */ -static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) +METHOD(stroke_cred_t, cache_cert, void, + private_stroke_cred_t *this, certificate_t *cert) { if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl) { @@ -292,10 +388,8 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) } } -/** - * Implementation of stroke_cred_t.cachecrl. - */ -static void cachecrl(private_stroke_cred_t *this, bool enabled) +METHOD(stroke_cred_t, cachecrl, void, + private_stroke_cred_t *this, bool enabled) { DBG1(DBG_CFG, "crl caching to %s %s", CRL_DIR, enabled ? "enabled" : "disabled"); @@ -852,7 +946,6 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, if (line.len > strlen("include ") && strneq(line.ptr, "include ", strlen("include "))) { - glob_t buf; char **expanded, *dir, pattern[PATH_MAX]; u_char *pos; @@ -894,18 +987,27 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, dir, (int)line.len, line.ptr); free(dir); } - if (glob(pattern, GLOB_ERR, NULL, &buf) != 0) +#ifdef HAVE_GLOB_H { - DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern); - } - else - { - for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) + glob_t buf; + if (glob(pattern, GLOB_ERR, NULL, &buf) != 0) { - load_secrets(this, *expanded, level + 1, prompt); + DBG1(DBG_CFG, "expanding file expression '%s' failed", + pattern); } + else + { + for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) + { + load_secrets(this, *expanded, level + 1, prompt); + } + } + globfree(&buf); } - globfree(&buf); +#else /* HAVE_GLOB_H */ + /* if glob(3) is not available, try to load pattern directly */ + load_secrets(this, pattern, level + 1, prompt); +#endif /* HAVE_GLOB_H */ continue; } @@ -994,10 +1096,8 @@ static void load_certs(private_stroke_cred_t *this) load_certdir(this, CRL_DIR, CERT_X509_CRL, 0); } -/** - * Implementation of stroke_cred_t.reread. - */ -static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt) +METHOD(stroke_cred_t, reread, void, + private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt) { if (msg->reread.flags & REREAD_SECRETS) { @@ -1037,10 +1137,14 @@ static void reread(private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt) } } -/** - * Implementation of stroke_cred_t.destroy - */ -static void destroy(private_stroke_cred_t *this) +METHOD(stroke_cred_t, add_shared, void, + private_stroke_cred_t *this, shared_key_t *shared, linked_list_t *owners) +{ + this->creds->add_shared_list(this->creds, shared, owners); +} + +METHOD(stroke_cred_t, destroy, void, + private_stroke_cred_t *this) { lib->credmgr->remove_set(lib->credmgr, &this->creds->set); this->creds->destroy(this->creds); @@ -1052,27 +1156,36 @@ static void destroy(private_stroke_cred_t *this) */ stroke_cred_t *stroke_cred_create() { - private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)return_null; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)cache_cert; - this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg, FILE*))reread; - this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca; - this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer; - this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl; - this->public.destroy = (void(*)(stroke_cred_t*))destroy; - - this->creds = mem_cred_create(); + private_stroke_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = (void*)return_null, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)_cache_cert, + }, + .reread = _reread, + .load_ca = _load_ca, + .load_peer = _load_peer, + .load_pubkey = _load_pubkey, + .add_shared = _add_shared, + .cachecrl = _cachecrl, + .destroy = _destroy, + }, + .creds = mem_cred_create(), + ); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); + this->force_ca_cert = lib->settings->get_bool(lib->settings, + "charon.plugins.stroke.ignore_missing_ca_basic_constraint", FALSE); + load_certs(this); load_secrets(this, SECRETS_FILE, 0, NULL); - this->cachecrl = FALSE; - return &this->public; } diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h index ccee7d87c..83e648819 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.h +++ b/src/libcharon/plugins/stroke/stroke_cred.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -26,6 +27,7 @@ #include <stroke_msg.h> #include <credentials/credential_set.h> #include <credentials/certificates/certificate.h> +#include <utils/linked_list.h> typedef struct stroke_cred_t stroke_cred_t; @@ -56,7 +58,7 @@ struct stroke_cred_t { certificate_t* (*load_ca)(stroke_cred_t *this, char *filename); /** - * Load a peer certificate and serve it rhrough the credential_set. + * Load a peer certificate and serve it through the credential_set. * * @param filename file to load peer cert from * @return reference to loaded certificate, or NULL @@ -64,6 +66,26 @@ struct stroke_cred_t { certificate_t* (*load_peer)(stroke_cred_t *this, char *filename); /** + * Load a raw public key and serve it through the credential_set. + * + * @param type type of the raw public key (RSA or ECDSA) + * @param filename file to load raw public key from + * @param identity identity of the raw public key owner + * @return reference to loaded raw public key, or NULL + */ + certificate_t* (*load_pubkey)(stroke_cred_t *this, key_type_t type, + char *filename, identification_t *identity); + + /** + * Add a shared secret to serve through the credential_set. + * + * @param shared shared key to add, gets owned + * @param owners list of owners (identification_t*), gets owned + */ + void (*add_shared)(stroke_cred_t *this, shared_key_t *shared, + linked_list_t *owners); + + /** * Enable/Disable CRL caching to disk. * * @param enabled TRUE to enable, FALSE to disable diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 6c42f8f8a..514a91e2b 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -15,6 +15,7 @@ #include "stroke_list.h" +#include <inttypes.h> #include <time.h> #ifdef HAVE_MALLINFO @@ -24,6 +25,7 @@ #include <hydra.h> #include <daemon.h> #include <utils/linked_list.h> +#include <plugins/plugin.h> #include <credentials/certificates/x509.h> #include <credentials/certificates/ac.h> #include <credentials/certificates/crl.h> @@ -116,7 +118,7 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) ike_proposal = ike_sa->get_proposal(ike_sa); - fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s", + fprintf(out, "%12s[%d]: IKE SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s", ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "", id->get_responder_spi(id), id->is_initiator(id) ? "" : "*"); @@ -221,11 +223,14 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) { u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED; u_int16_t encr_size = 0, int_size = 0; + u_int16_t esn = NO_EXT_SEQ_NUMBERS; proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &encr_alg, &encr_size); proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &int_size); + proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, + &esn, NULL); if (encr_alg != ENCR_UNDEFINED) { @@ -243,21 +248,25 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) fprintf(out, "_%u", int_size); } } + if (esn == EXT_SEQ_NUMBERS) + { + fprintf(out, "/ESN"); + } } now = time_monotonic(NULL); child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in); - fprintf(out, ", %llu bytes_i", bytes_in); + fprintf(out, ", %" PRIu64 " bytes_i", bytes_in); if (use_in) { - fprintf(out, " (%ds ago)", now - use_in); + fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_in)); } child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out); - fprintf(out, ", %llu bytes_o", bytes_out); + fprintf(out, ", %" PRIu64 " bytes_o", bytes_out); if (use_out) { - fprintf(out, " (%ds ago)", now - use_out); + fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_out)); } fprintf(out, ", rekeying "); @@ -324,7 +333,7 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local) { if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR)) { - fprintf(out, "EAP_%d-%d authentication", + fprintf(out, "EAP_%" PRIuPTR "-%" PRIuPTR " authentication", (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE), (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR)); } @@ -389,25 +398,27 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local) } METHOD(stroke_list_t, status, void, - private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all) + private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, + bool all, bool wait) { enumerator_t *enumerator, *children; ike_cfg_t *ike_cfg; child_cfg_t *child_cfg; child_sa_t *child_sa; ike_sa_t *ike_sa; + linked_list_t *my_ts, *other_ts; bool first, found = FALSE; char *name = msg->status.name; + u_int half_open; if (all) { peer_cfg_t *peer_cfg; - plugin_t *plugin; char *pool; host_t *host; u_int32_t dpd; time_t since, now; - u_int size, online, offline; + u_int size, online, offline, i; now = time_monotonic(NULL); since = time(NULL) - (now - this->uptime); @@ -421,21 +432,24 @@ METHOD(stroke_list_t, status, void, mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks); } #endif /* HAVE_MALLINFO */ - fprintf(out, " worker threads: %d idle of %d,", + fprintf(out, " worker threads: %d of %d idle, ", lib->processor->get_idle_threads(lib->processor), lib->processor->get_total_threads(lib->processor)); - fprintf(out, " job queue load: %d,", - lib->processor->get_job_load(lib->processor)); - fprintf(out, " scheduled events: %d\n", - lib->scheduler->get_job_load(lib->scheduler)); - fprintf(out, " loaded plugins: "); - enumerator = lib->plugins->create_plugin_enumerator(lib->plugins); - while (enumerator->enumerate(enumerator, &plugin)) + for (i = 0; i < JOB_PRIO_MAX; i++) { - fprintf(out, "%s ", plugin->get_name(plugin)); + fprintf(out, "%s%d", i == 0 ? "" : "/", + lib->processor->get_working_threads(lib->processor, i)); } - enumerator->destroy(enumerator); - fprintf(out, "\n"); + fprintf(out, " working, job queue: "); + for (i = 0; i < JOB_PRIO_MAX; i++) + { + fprintf(out, "%s%d", i == 0 ? "" : "/", + lib->processor->get_job_load(lib->processor, i)); + } + fprintf(out, ", scheduled: %d\n", + lib->scheduler->get_job_load(lib->scheduler)); + fprintf(out, " loaded plugins: %s\n", + lib->plugins->loaded_plugins(lib->plugins)); first = TRUE; enumerator = this->attribute->create_pool_enumerator(this->attribute); @@ -491,12 +505,11 @@ METHOD(stroke_list_t, status, void, children = peer_cfg->create_child_cfg_enumerator(peer_cfg); while (children->enumerate(children, &child_cfg)) { - linked_list_t *my_ts, *other_ts; - my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL); - fprintf(out, "%12s: child: %#R=== %#R", child_cfg->get_name(child_cfg), - my_ts, other_ts); + fprintf(out, "%12s: child: %#R=== %#R%N", + child_cfg->get_name(child_cfg), my_ts, other_ts, + ipsec_mode_names, child_cfg->get_mode(child_cfg)); my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); @@ -512,10 +525,39 @@ METHOD(stroke_list_t, status, void, enumerator->destroy(enumerator); } + /* Enumerate shunt policies */ + first = TRUE; + enumerator = charon->shunts->create_enumerator(charon->shunts); + while (enumerator->enumerate(enumerator, &child_cfg)) + { + if (name && !streq(name, child_cfg->get_name(child_cfg))) + { + continue; + } + if (first) + { + fprintf(out, "Shunted Connections:\n"); + first = FALSE; + } + my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL); + other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL); + fprintf(out, "%12s: %#R=== %#R%N\n", + child_cfg->get_name(child_cfg), my_ts, other_ts, + ipsec_mode_names, child_cfg->get_mode(child_cfg)); + my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); + other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); + } + enumerator->destroy(enumerator); + + /* Enumerate traps */ first = TRUE; enumerator = charon->traps->create_enumerator(charon->traps); while (enumerator->enumerate(enumerator, NULL, &child_sa)) { + if (name && !streq(name, child_sa->get_name(child_sa))) + { + continue; + } if (first) { fprintf(out, "Routed Connections:\n"); @@ -525,12 +567,17 @@ METHOD(stroke_list_t, status, void, } enumerator->destroy(enumerator); - fprintf(out, "Security Associations:\n"); - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + half_open = charon->ike_sa_manager->get_half_open_count( + charon->ike_sa_manager, NULL); + fprintf(out, "Security Associations (%u up, %u connecting):\n", + charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open, + half_open); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, wait); while (enumerator->enumerate(enumerator, &ike_sa)) { bool ike_printed = FALSE; - iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa); + enumerator_t *children = ike_sa->create_child_sa_enumerator(ike_sa); if (name == NULL || streq(name, ike_sa->get_name(ike_sa))) { @@ -539,7 +586,7 @@ METHOD(stroke_list_t, status, void, ike_printed = TRUE; } - while (children->iterate(children, (void**)&child_sa)) + while (children->enumerate(children, (void**)&child_sa)) { if (name == NULL || streq(name, child_sa->get_name(child_sa))) { @@ -582,35 +629,30 @@ static linked_list_t* create_unique_cert_list(certificate_type_t type) while (enumerator->enumerate(enumerator, (void**)&cert)) { - iterator_t *iterator = list->create_iterator(list, TRUE); + enumerator_t *added = list->create_enumerator(list); identification_t *issuer = cert->get_issuer(cert); - bool previous_same, same = FALSE, last = TRUE; + bool previous_same, same = FALSE, found = FALSE; certificate_t *list_cert; - while (iterator->iterate(iterator, (void**)&list_cert)) + while (added->enumerate(added, (void**)&list_cert)) { - /* exit if we have a duplicate? */ if (list_cert->equals(list_cert, cert)) - { - last = FALSE; + { /* stop if we found a duplicate*/ + found = TRUE; break; } - /* group certificates with same issuer */ previous_same = same; same = list_cert->has_issuer(list_cert, issuer); if (previous_same && !same) - { - iterator->insert_before(iterator, (void *)cert->get_ref(cert)); - last = FALSE; + { /* group certificates with same issuer */ break; } } - iterator->destroy(iterator); - - if (last) + if (!found) { - list->insert_last(list, (void *)cert->get_ref(cert)); + list->insert_before(list, added, cert->get_ref(cert)); } + added->destroy(added); } enumerator->destroy(enumerator); return list; @@ -657,12 +699,14 @@ static void list_public_key(public_key_t *public, FILE *out) static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out) { bool first = TRUE; - - enumerator_t *enumerator = list->create_enumerator(list); + time_t now = time(NULL), notBefore, notAfter; + enumerator_t *enumerator; certificate_t *cert; + enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, (void**)&cert)) { + identification_t *subject = cert->get_subject(cert); public_key_t *public = cert->get_public_key(cert); if (public) @@ -675,6 +719,41 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out) } fprintf(out, "\n"); + /* list subject if available */ + if (subject->get_type(subject) != ID_KEY_ID) + { + fprintf(out, " subject: %#Y\n", subject); + } + + /* list validity if available*/ + cert->get_validity(cert, &now, ¬Before, ¬After); + if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME) + { + fprintf(out, " validity: not before %T, ", ¬Before, utc); + if (now < notBefore) + { + fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); + } + else + { + fprintf(out, "ok\n"); + } + fprintf(out, " not after %T, ", ¬After, utc); + if (now > notAfter) + { + fprintf(out, "expired (%V ago)\n", &now, ¬After); + } + else + { + fprintf(out, "ok"); + if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) + { + fprintf(out, " (expires in %V)", &now, ¬After); + } + fprintf(out, " \n"); + } + } + list_public_key(public, out); public->destroy(public); } @@ -791,7 +870,7 @@ static void stroke_list_certs(linked_list_t *list, char *label, fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert)); fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); - serial = x509->get_serial(x509); + serial = chunk_skip_zero(x509->get_serial(x509)); fprintf(out, " serial: %#B\n", &serial); /* list validity */ @@ -904,7 +983,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) { fprintf(out, " hissuer: \"%Y\"\n", id); } - chunk = ac->get_holderSerial(ac); + chunk = chunk_skip_zero(ac->get_holderSerial(ac)); if (chunk.ptr) { fprintf(out, " hserial: %#B\n", &chunk); @@ -916,7 +995,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) groups->destroy(groups); } fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); - chunk = ac->get_serial(ac); + chunk = chunk_skip_zero(ac->get_serial(ac)); fprintf(out, " serial: %#B\n", &chunk); /* list validity */ @@ -973,13 +1052,14 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out) fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); /* list optional crlNumber */ - chunk = crl->get_serial(crl); + chunk = chunk_skip_zero(crl->get_serial(crl)); if (chunk.ptr) { fprintf(out, " serial: %#B\n", &chunk); } if (crl->is_delta_crl(crl, &chunk)) { + chunk = chunk_skip_zero(chunk); fprintf(out, " delta for: %#B\n", &chunk); } @@ -1157,6 +1237,58 @@ static void list_algs(FILE *out) fprintf(out, "\n"); } +/** + * List loaded plugin information + */ +static void list_plugins(FILE *out) +{ + plugin_feature_t *features, *fp; + enumerator_t *enumerator; + linked_list_t *list; + plugin_t *plugin; + int count, i; + bool loaded; + char *str; + + fprintf(out, "\n"); + fprintf(out, "List of loaded Plugins:\n"); + fprintf(out, "\n"); + + enumerator = lib->plugins->create_plugin_enumerator(lib->plugins); + while (enumerator->enumerate(enumerator, &plugin, &list)) + { + fprintf(out, "%s:\n", plugin->get_name(plugin)); + if (plugin->get_features) + { + count = plugin->get_features(plugin, &features); + for (i = 0; i < count; i++) + { + str = plugin_feature_get_string(&features[i]); + switch (features[i].kind) + { + case FEATURE_PROVIDE: + fp = &features[i]; + loaded = list->find_first(list, NULL, + (void**)&fp) == SUCCESS; + fprintf(out, " %s%s\n", + str, loaded ? "" : " (not loaded)"); + break; + case FEATURE_DEPENDS: + fprintf(out, " %s\n", str); + break; + case FEATURE_SDEPEND: + fprintf(out, " %s(soft)\n", str); + break; + default: + break; + } + free(str); + } + } + } + enumerator->destroy(enumerator); +} + METHOD(stroke_list_t, list, void, private_stroke_list_t *this, stroke_msg_t *msg, FILE *out) { @@ -1228,6 +1360,10 @@ METHOD(stroke_list_t, list, void, { list_algs(out); } + if (msg->list.flags & LIST_PLUGINS) + { + list_plugins(out); + } } /** diff --git a/src/libcharon/plugins/stroke/stroke_list.h b/src/libcharon/plugins/stroke/stroke_list.h index b5bedc6c2..a0d2d18cc 100644 --- a/src/libcharon/plugins/stroke/stroke_list.h +++ b/src/libcharon/plugins/stroke/stroke_list.h @@ -47,8 +47,10 @@ struct stroke_list_t { * @param msg stroke message * @param out stroke console stream * @param all TRUE for "statusall" + * @param wait TRUE to wait for IKE_SA entries, FALSE to skip if locked */ - void (*status)(stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all); + void (*status)(stroke_list_t *this, stroke_msg_t *msg, FILE *out, + bool all, bool wait); /** * Log pool leases to stroke console. diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 88d0270d8..57648feb8 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2011-2012 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -20,13 +21,15 @@ #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> -#include <sys/fcntl.h> #include <unistd.h> #include <errno.h> #include <hydra.h> #include <daemon.h> +#include <threading/mutex.h> #include <threading/thread.h> +#include <threading/condvar.h> +#include <utils/linked_list.h> #include <processing/jobs/callback_job.h> #include "stroke_config.h" @@ -36,6 +39,12 @@ #include "stroke_attribute.h" #include "stroke_list.h" +/** + * To avoid clogging the thread pool with (blocking) jobs, we limit the number + * of concurrently handled stroke commands. + */ +#define MAX_CONCURRENT_DEFAULT 4 + typedef struct stroke_job_context_t stroke_job_context_t; typedef struct private_stroke_socket_t private_stroke_socket_t; @@ -57,7 +66,37 @@ struct private_stroke_socket_t { /** * job accepting stroke messages */ - callback_job_t *job; + callback_job_t *receiver; + + /** + * job handling stroke messages + */ + callback_job_t *handler; + + /** + * queued stroke commands + */ + linked_list_t *commands; + + /** + * lock for command list + */ + mutex_t *mutex; + + /** + * condvar to signal the arrival or completion of commands + */ + condvar_t *condvar; + + /** + * the number of currently handled commands + */ + u_int handling; + + /** + * the maximum number of concurrently handled commands + */ + u_int max_concurrent; /** * configuration backend @@ -85,7 +124,7 @@ struct private_stroke_socket_t { stroke_ca_t *ca; /** - * Status information logging + * status information logging */ stroke_list_t *list; }; @@ -146,6 +185,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end) pop_string(msg, &end->auth2); pop_string(msg, &end->id); pop_string(msg, &end->id2); + pop_string(msg, &end->rsakey); pop_string(msg, &end->cert); pop_string(msg, &end->cert2); pop_string(msg, &end->ca); @@ -161,6 +201,7 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end) DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2); DBG2(DBG_CFG, " %sid=%s", label, end->id); DBG2(DBG_CFG, " %sid2=%s", label, end->id2); + DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey); DBG2(DBG_CFG, " %scert=%s", label, end->cert); DBG2(DBG_CFG, " %scert2=%s", label, end->cert2); DBG2(DBG_CFG, " %sca=%s", label, end->ca); @@ -190,6 +231,9 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity); DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike); DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp); + DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay); + DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action); + DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action); DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no"); DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by); DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid); @@ -322,11 +366,11 @@ static void stroke_del_ca(private_stroke_socket_t *this, * show status of daemon */ static void stroke_status(private_stroke_socket_t *this, - stroke_msg_t *msg, FILE *out, bool all) + stroke_msg_t *msg, FILE *out, bool all, bool wait) { pop_string(msg, &(msg->status.name)); - this->list->status(this->list, msg, out, all); + this->list->status(this->list, msg, out, all, wait); } /** @@ -382,7 +426,7 @@ static void stroke_export(private_stroke_socket_t *this, { pop_string(msg, &msg->export.selector); - if (msg->purge.flags & EXPORT_X509) + if (msg->export.flags & EXPORT_X509) { enumerator_t *enumerator; identification_t *id; @@ -418,6 +462,33 @@ static void stroke_leases(private_stroke_socket_t *this, } /** + * Show memory usage + */ +static void stroke_memusage(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + if (lib->leak_detective) + { + lib->leak_detective->usage(lib->leak_detective, out); + } +} + +/** + * Set username and password for a connection + */ +static void stroke_user_creds(private_stroke_socket_t *this, + stroke_msg_t *msg, FILE *out) +{ + pop_string(msg, &msg->user_creds.name); + pop_string(msg, &msg->user_creds.username); + pop_string(msg, &msg->user_creds.password); + + DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name); + + this->config->set_user_credentials(this->config, msg, out); +} + +/** * set the verbosity debug output */ static void stroke_loglevel(private_stroke_socket_t *this, @@ -433,7 +504,7 @@ static void stroke_loglevel(private_stroke_socket_t *this, msg->loglevel.level, msg->loglevel.type); group = enum_from_name(debug_names, msg->loglevel.type); - if (group < 0) + if ((int)group < 0) { fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); return; @@ -475,6 +546,18 @@ static void stroke_job_context_destroy(stroke_job_context_t *this) } /** + * called to signal the completion of a command + */ +static inline job_requeue_t job_processed(private_stroke_socket_t *this) +{ + this->mutex->lock(this->mutex); + this->handling--; + this->condvar->signal(this->condvar); + this->mutex->unlock(this->mutex); + return JOB_REQUEUE_NONE; +} + +/** * process a stroke request from the socket pointed by "fd" */ static job_requeue_t process(stroke_job_context_t *ctx) @@ -492,7 +575,7 @@ static job_requeue_t process(stroke_job_context_t *ctx) { DBG1(DBG_CFG, "reading length of stroke message failed: %s", strerror(errno)); - return JOB_REQUEUE_NONE; + return job_processed(this); } /* read message */ @@ -501,14 +584,14 @@ static job_requeue_t process(stroke_job_context_t *ctx) if (bytes_read != msg_length) { DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno)); - return JOB_REQUEUE_NONE; + return job_processed(this); } out = fdopen(strokefd, "w+"); if (out == NULL) { DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno)); - return JOB_REQUEUE_NONE; + return job_processed(this); } DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length); @@ -534,10 +617,13 @@ static job_requeue_t process(stroke_job_context_t *ctx) stroke_rekey(this, msg, out); break; case STR_STATUS: - stroke_status(this, msg, out, FALSE); + stroke_status(this, msg, out, FALSE, TRUE); break; case STR_STATUS_ALL: - stroke_status(this, msg, out, TRUE); + stroke_status(this, msg, out, TRUE, TRUE); + break; + case STR_STATUS_ALL_NOBLK: + stroke_status(this, msg, out, TRUE, FALSE); break; case STR_ADD_CONN: stroke_add_conn(this, msg); @@ -572,6 +658,12 @@ static job_requeue_t process(stroke_job_context_t *ctx) case STR_LEASES: stroke_leases(this, msg, out); break; + case STR_MEMUSAGE: + stroke_memusage(this, msg, out); + break; + case STR_USER_CREDS: + stroke_user_creds(this, msg, out); + break; default: DBG1(DBG_CFG, "received unknown stroke"); break; @@ -579,11 +671,38 @@ static job_requeue_t process(stroke_job_context_t *ctx) fclose(out); /* fclose() closes underlying FD */ ctx->fd = 0; - return JOB_REQUEUE_NONE; + return job_processed(this); +} + +/** + * Handle queued stroke commands + */ +static job_requeue_t handle(private_stroke_socket_t *this) +{ + stroke_job_context_t *ctx; + callback_job_t *job; + bool oldstate; + + this->mutex->lock(this->mutex); + thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex); + oldstate = thread_cancelability(TRUE); + while (this->commands->get_count(this->commands) == 0 || + this->handling >= this->max_concurrent) + { + this->condvar->wait(this->condvar, this->mutex); + } + thread_cancelability(oldstate); + this->commands->remove_first(this->commands, (void**)&ctx); + this->handling++; + thread_cleanup_pop(TRUE); + job = callback_job_create_with_prio((callback_job_cb_t)process, ctx, + (void*)stroke_job_context_destroy, this->handler, JOB_PRIO_HIGH); + lib->processor->queue_job(lib->processor, (job_t*)job); + return JOB_REQUEUE_DIRECT; } /** - * Implementation of private_stroke_socket_t.stroke_receive. + * Accept stroke commands and queue them to be handled */ static job_requeue_t receive(private_stroke_socket_t *this) { @@ -591,7 +710,6 @@ static job_requeue_t receive(private_stroke_socket_t *this) int strokeaddrlen = sizeof(strokeaddr); int strokefd; bool oldstate; - callback_job_t *job; stroke_job_context_t *ctx; oldstate = thread_cancelability(TRUE); @@ -604,17 +722,18 @@ static job_requeue_t receive(private_stroke_socket_t *this) return JOB_REQUEUE_FAIR; } - ctx = malloc_thing(stroke_job_context_t); - ctx->fd = strokefd; - ctx->this = this; - job = callback_job_create((callback_job_cb_t)process, - ctx, (void*)stroke_job_context_destroy, this->job); - lib->processor->queue_job(lib->processor, (job_t*)job); + INIT(ctx, + .fd = strokefd, + .this = this, + ); + this->mutex->lock(this->mutex); + this->commands->insert_last(this->commands, ctx); + this->condvar->signal(this->condvar); + this->mutex->unlock(this->mutex); return JOB_REQUEUE_FAIR; } - /** * initialize and open stroke socket */ @@ -659,12 +778,14 @@ static bool open_socket(private_stroke_socket_t *this) return TRUE; } -/** - * Implementation of stroke_socket_t.destroy - */ -static void destroy(private_stroke_socket_t *this) +METHOD(stroke_socket_t, destroy, void, + private_stroke_socket_t *this) { - this->job->cancel(this->job); + this->handler->cancel(this->handler); + this->receiver->cancel(this->receiver); + this->commands->destroy_function(this->commands, (void*)stroke_job_context_destroy); + this->condvar->destroy(this->condvar); + this->mutex->destroy(this->mutex); lib->credmgr->remove_set(lib->credmgr, &this->ca->set); lib->credmgr->remove_set(lib->credmgr, &this->cred->set); charon->backends->remove_backend(charon->backends, &this->config->backend); @@ -683,9 +804,13 @@ static void destroy(private_stroke_socket_t *this) */ stroke_socket_t *stroke_socket_create() { - private_stroke_socket_t *this = malloc_thing(private_stroke_socket_t); + private_stroke_socket_t *this; - this->public.destroy = (void(*)(stroke_socket_t*))destroy; + INIT(this, + .public = { + .destroy = _destroy, + }, + ); if (!open_socket(this)) { @@ -700,14 +825,24 @@ stroke_socket_t *stroke_socket_create() this->control = stroke_control_create(); this->list = stroke_list_create(this->attribute); + this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); + this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT); + this->commands = linked_list_create(); + this->max_concurrent = lib->settings->get_int(lib->settings, + "charon.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT); + lib->credmgr->add_set(lib->credmgr, &this->ca->set); lib->credmgr->add_set(lib->credmgr, &this->cred->set); charon->backends->add_backend(charon->backends, &this->config->backend); hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider); - this->job = callback_job_create((callback_job_cb_t)receive, - this, NULL, NULL); - lib->processor->queue_job(lib->processor, (job_t*)this->job); + this->receiver = 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->receiver); + + this->handler = callback_job_create_with_prio((callback_job_cb_t)handle, + this, NULL, NULL, JOB_PRIO_CRITICAL); + lib->processor->queue_job(lib->processor, (job_t*)this->handler); return &this->public; } diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am new file mode 100644 index 000000000..b8a57b119 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon ${axis2c_CFLAGS} + +AM_CFLAGS = -rdynamic + +libstrongswan_tnc_ifmap_la_LIBADD = ${axis2c_LIBS} -laxutil -laxis2_engine -laxis2_http_sender + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la +else +plugin_LTLIBRARIES = libstrongswan-tnc-ifmap.la +endif + +libstrongswan_tnc_ifmap_la_SOURCES = \ + tnc_ifmap_plugin.h tnc_ifmap_plugin.c \ + tnc_ifmap_listener.h tnc_ifmap_listener.c \ + tnc_ifmap_soap.h tnc_ifmap_soap.c + +libstrongswan_tnc_ifmap_la_LDFLAGS = -module -avoid-version + diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in new file mode 100644 index 000000000..54deb7cd7 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in @@ -0,0 +1,620 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/tnc_ifmap +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_tnc_ifmap_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_tnc_ifmap_la_OBJECTS = tnc_ifmap_plugin.lo \ + tnc_ifmap_listener.lo tnc_ifmap_soap.lo +libstrongswan_tnc_ifmap_la_OBJECTS = \ + $(am_libstrongswan_tnc_ifmap_la_OBJECTS) +libstrongswan_tnc_ifmap_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnc_ifmap_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_tnc_ifmap_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_tnc_ifmap_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_tnc_ifmap_la_SOURCES) +DIST_SOURCES = $(libstrongswan_tnc_ifmap_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon ${axis2c_CFLAGS} + +AM_CFLAGS = -rdynamic +libstrongswan_tnc_ifmap_la_LIBADD = ${axis2c_LIBS} -laxutil -laxis2_engine -laxis2_http_sender +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-ifmap.la +libstrongswan_tnc_ifmap_la_SOURCES = \ + tnc_ifmap_plugin.h tnc_ifmap_plugin.c \ + tnc_ifmap_listener.h tnc_ifmap_listener.c \ + tnc_ifmap_soap.h tnc_ifmap_soap.c + +libstrongswan_tnc_ifmap_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_ifmap/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_ifmap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-tnc-ifmap.la: $(libstrongswan_tnc_ifmap_la_OBJECTS) $(libstrongswan_tnc_ifmap_la_DEPENDENCIES) + $(libstrongswan_tnc_ifmap_la_LINK) $(am_libstrongswan_tnc_ifmap_la_rpath) $(libstrongswan_tnc_ifmap_la_OBJECTS) $(libstrongswan_tnc_ifmap_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_ifmap_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_ifmap_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_ifmap_soap.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c new file mode 100644 index 000000000..4fd33696c --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c @@ -0,0 +1,173 @@ +/* + * 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. + */ + +#include "tnc_ifmap_listener.h" +#include "tnc_ifmap_soap.h" + +#include <daemon.h> +#include <hydra.h> +#include <debug.h> + +typedef struct private_tnc_ifmap_listener_t private_tnc_ifmap_listener_t; + +/** + * Private data of an tnc_ifmap_listener_t object. + */ +struct private_tnc_ifmap_listener_t { + + /** + * Public tnc_ifmap_listener_t interface. + */ + tnc_ifmap_listener_t public; + + /** + * TNC IF-MAP 2.0 SOAP interface + */ + tnc_ifmap_soap_t *ifmap; + +}; + +/** + * Publish PEP device-ip metadata + */ +static bool publish_device_ip_addresses(private_tnc_ifmap_listener_t *this) +{ + enumerator_t *enumerator; + host_t *host; + bool success = TRUE; + + enumerator = hydra->kernel_interface->create_address_enumerator( + hydra->kernel_interface, FALSE, FALSE); + while (enumerator->enumerate(enumerator, &host)) + { + if (!this->ifmap->publish_device_ip(this->ifmap, host)) + { + success = FALSE; + break; + } + } + enumerator->destroy(enumerator); + + return success; +} + +/** + * Publish all IKE_SA metadata + */ +static bool reload_metadata(private_tnc_ifmap_listener_t *this) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + bool success = TRUE; + + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, FALSE); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED) + { + continue; + } + if (!this->ifmap->publish_ike_sa(this->ifmap, ike_sa, TRUE)) + { + success = FALSE; + break; + } + } + enumerator->destroy(enumerator); + + return success; +} + +METHOD(listener_t, ike_updown, bool, + private_tnc_ifmap_listener_t *this, ike_sa_t *ike_sa, bool up) +{ + if (ike_sa->get_state(ike_sa) != IKE_CONNECTING) + { + this->ifmap->publish_ike_sa(this->ifmap, ike_sa, up); + } + return TRUE; +} + +METHOD(listener_t, alert, bool, + private_tnc_ifmap_listener_t *this, ike_sa_t *ike_sa, alert_t alert, + va_list args) +{ + if (alert == ALERT_PEER_AUTH_FAILED) + { + this->ifmap->publish_enforcement_report(this->ifmap, + ike_sa->get_other_host(ike_sa), + "block", "authentication failed"); + } + return TRUE; +} + +METHOD(tnc_ifmap_listener_t, destroy, void, + private_tnc_ifmap_listener_t *this) +{ + DESTROY_IF(this->ifmap); + free(this); +} + +/** + * See header + */ +tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload) +{ + private_tnc_ifmap_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_updown = _ike_updown, + .alert = _alert, + }, + .destroy = _destroy, + }, + .ifmap = tnc_ifmap_soap_create(), + ); + + if (!this->ifmap) + { + destroy(this); + return NULL; + } + if (!this->ifmap->newSession(this->ifmap)) + { + destroy(this); + return NULL; + } + if (!this->ifmap->purgePublisher(this->ifmap)) + { + destroy(this); + return NULL; + } + if (!publish_device_ip_addresses(this)) + { + destroy(this); + return NULL; + } + if (reload) + { + if (!reload_metadata(this)) + { + destroy(this); + return NULL; + } + } + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h new file mode 100644 index 000000000..878505b38 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.h @@ -0,0 +1,51 @@ +/* + * 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_ifmap_listener tnc_ifmap_listener + * @{ @ingroup tnc_ifmap + */ + +#ifndef TNC_IFMAP_LISTENER_H_ +#define TNC_IFMAP_LISTENER_H_ + +#include <bus/bus.h> + +typedef struct tnc_ifmap_listener_t tnc_ifmap_listener_t; + +/** + * Listener which collects information on IKE_SAs + */ +struct tnc_ifmap_listener_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a tnc_ifmap_listener_t. + */ + void (*destroy)(tnc_ifmap_listener_t *this); +}; + +/** + * Create a tnc_ifmap_listener instance. + * + * @param reload reload all IKE_SA metadata + */ +tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload); + +#endif /** TNC_IFMAP_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c new file mode 100644 index 000000000..de4d12e0b --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.c @@ -0,0 +1,99 @@ +/* + * 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. + */ + +#include "tnc_ifmap_plugin.h" +#include "tnc_ifmap_listener.h" + +#include <daemon.h> + +typedef struct private_tnc_ifmap_plugin_t private_tnc_ifmap_plugin_t; + +/** + * private data of tnc_ifmap plugin + */ +struct private_tnc_ifmap_plugin_t { + + /** + * implements plugin interface + */ + tnc_ifmap_plugin_t public; + + /** + * Listener interface, listens to CHILD_SA state changes + */ + tnc_ifmap_listener_t *listener; +}; + +METHOD(plugin_t, get_name, char*, + private_tnc_ifmap_plugin_t *this) +{ + return "tnc-ifmap"; +} + +METHOD(plugin_t, reload, bool, + private_tnc_ifmap_plugin_t *this) +{ + if (this->listener) + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + } + + this->listener = tnc_ifmap_listener_create(TRUE); + if (!this->listener) + { + return FALSE; + } + + charon->bus->add_listener(charon->bus, &this->listener->listener); + return TRUE; +} + +METHOD(plugin_t, destroy, void, + private_tnc_ifmap_plugin_t *this) +{ + if (this->listener) + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + } + free(this); +} + +/* + * see header file + */ +plugin_t *tnc_ifmap_plugin_create() +{ + private_tnc_ifmap_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = _reload, + .destroy = _destroy, + }, + }, + .listener = tnc_ifmap_listener_create(FALSE), + ); + + if (this->listener) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h new file mode 100644 index 000000000..8172be7c9 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_plugin.h @@ -0,0 +1,42 @@ +/* + * 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_ifmap tnc_ifmap + * @ingroup cplugins + * + * @defgroup tnc_ifmap_plugin tnc_ifmap_plugin + * @{ @ingroup tnc_ifmap + */ + +#ifndef TNC_IFMAP_PLUGIN_H_ +#define TNC_IFMAP_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct tnc_ifmap_plugin_t tnc_ifmap_plugin_t; + +/** + * TNC IF-MAP plugin + */ +struct tnc_ifmap_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** TNC_IFMAP_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c new file mode 100644 index 000000000..913cdab12 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c @@ -0,0 +1,859 @@ +/* + * 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. + */ + +#include "tnc_ifmap_soap.h" + +#include <debug.h> + +#include <axis2_util.h> +#include <axis2_client.h> +#include <axis2_http_transport.h> +#include <axis2_http_transport_sender.h> +#include <axiom_soap.h> + +#define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2" +#define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2" +#define IFMAP_LOGFILE "strongswan_ifmap.log" +#define IFMAP_SERVER "https://localhost:8443/" + +typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t; + +/** + * Private data of an tnc_ifmap_soap_t object. + */ +struct private_tnc_ifmap_soap_t { + + /** + * Public tnc_ifmap_soap_t interface. + */ + tnc_ifmap_soap_t public; + + /** + * Axis2/C environment + */ + axutil_env_t *env; + + /** + * Axis2 service client + */ + axis2_svc_client_t* svc_client; + + /** + * SOAP Session ID + */ + char *session_id; + + /** + * IF-MAP Publisher ID + */ + char *ifmap_publisher_id; + + /** + * PEP and PDP device name + */ + char *device_name; + +}; + +/** + * Send request and receive result via SOAP + */ +static axiom_element_t* send_receive(private_tnc_ifmap_soap_t *this, + char *request_qname, axiom_node_t *request, + char *receipt_qname, axiom_node_t **result) + +{ + axiom_node_t *parent, *node; + axiom_element_t *parent_el, *el; + axutil_qname_t *qname; + + /* send request and receive result */ + DBG2(DBG_TNC, "sending ifmap %s", request_qname); + + parent = axis2_svc_client_send_receive(this->svc_client, this->env, request); + if (!parent) + { + DBG1(DBG_TNC, "no ifmap %s received from MAP server", receipt_qname); + return NULL; + } + DBG2(DBG_TNC, "received ifmap %s", receipt_qname); + + /* extract the parent element */ + parent_el = (axiom_element_t*)axiom_node_get_data_element(parent, this->env); + + /* look for a child node with the given receipt qname */ + qname = axutil_qname_create_from_string(this->env, strdup(receipt_qname)); + el = axiom_element_get_first_child_with_qname(parent_el, this->env, qname, + parent, &node); + axutil_qname_free(qname, this->env); + + if (el) + { + if (result) + { + *result = parent; + } + else + { + /* no further processing requested */ + axiom_node_free_tree(parent, this->env); + } + return el; + } + DBG1(DBG_TNC, "child node with qname '%s' not found", receipt_qname); + + /* free parent in the error case */ + axiom_node_free_tree(parent, this->env); + + return NULL; +} + +METHOD(tnc_ifmap_soap_t, newSession, bool, + private_tnc_ifmap_soap_t *this) +{ + axiom_node_t *request, *result; + axiom_element_t *el; + axiom_namespace_t *ns; + axis2_char_t *value; + + + /* build newSession request */ + ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); + el = axiom_element_create(this->env, NULL, "newSession", ns, &request); + + /* send newSession request and receive newSessionResult */ + el = send_receive(this, "newSession", request, "newSessionResult", &result); + if (!el) + { + return FALSE; + } + + /* get session-id */ + value = axiom_element_get_attribute_value_by_name(el, this->env, + "session-id"); + this->session_id = strdup(value); + + /* get ifmap-publisher-id */ + value = axiom_element_get_attribute_value_by_name(el, this->env, + "ifmap-publisher-id"); + this->ifmap_publisher_id = strdup(value); + + DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s", + this->session_id, this->ifmap_publisher_id); + + /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */ + this->device_name = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.device_name", + this->ifmap_publisher_id); + this->device_name = strdup(this->device_name); + + /* free result */ + axiom_node_free_tree(result, this->env); + + return this->session_id && this->ifmap_publisher_id; +} + +METHOD(tnc_ifmap_soap_t, purgePublisher, bool, + private_tnc_ifmap_soap_t *this) +{ + axiom_node_t *request; + axiom_element_t *el; + axiom_namespace_t *ns; + axiom_attribute_t *attr; + + /* build purgePublisher request */ + ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); + el = axiom_element_create(this->env, NULL, "purgePublisher", ns, &request); + attr = axiom_attribute_create(this->env, "session-id", + this->session_id, NULL); + axiom_element_add_attribute(el, this->env, attr, request); + attr = axiom_attribute_create(this->env, "ifmap-publisher-id", + this->ifmap_publisher_id, NULL); + axiom_element_add_attribute(el, this->env, attr, request); + + /* send purgePublisher request and receive purgePublisherReceived */ + return send_receive(this, "purgePublisher", request, + "purgePublisherReceived", NULL); +} + +/** + * Create an access-request based on device_name and ike_sa_id + */ +static axiom_node_t* create_access_request(private_tnc_ifmap_soap_t *this, + u_int32_t id) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN]; + + el = axiom_element_create(this->env, NULL, "access-request", NULL, &node); + + snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id); + attr = axiom_attribute_create(this->env, "name", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create an identity + */ +static axiom_node_t* create_identity(private_tnc_ifmap_soap_t *this, + identification_t *id, bool is_user) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN], *id_type; + + el = axiom_element_create(this->env, NULL, "identity", NULL, &node); + + snprintf(buf, BUF_LEN, "%Y", id); + attr = axiom_attribute_create(this->env, "name", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + switch (id->get_type(id)) + { + case ID_IPV4_ADDR: + id_type = "other"; + attr = axiom_attribute_create(this->env, "other-type-definition", + "36906:ipv4-address", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + break; + case ID_FQDN: + id_type = is_user ? "username" : "dns-name"; + break; + case ID_RFC822_ADDR: + id_type = "email-address"; + break; + case ID_IPV6_ADDR: + id_type = "other"; + attr = axiom_attribute_create(this->env, "other-type-definition", + "36906:ipv6-address", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + break; + case ID_DER_ASN1_DN: + id_type = "distinguished-name"; + break; + case ID_KEY_ID: + id_type = "other"; + attr = axiom_attribute_create(this->env, "other-type-definition", + "36906:key-id", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + break; + default: + id_type = "other"; + attr = axiom_attribute_create(this->env, "other-type-definition", + "36906:other", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + } + attr = axiom_attribute_create(this->env, "type", id_type, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create an ip-address + */ +static axiom_node_t* create_ip_address(private_tnc_ifmap_soap_t *this, + host_t *host) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN]; + + el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node); + + if (host->get_family(host) == AF_INET6) + { + chunk_t address; + int len, written, i; + char *pos; + bool first = TRUE; + + /* output IPv6 address in canonical IF-MAP 2.0 format */ + address = host->get_address(host); + pos = buf; + len = sizeof(buf); + + for (i = 0; i < address.len; i = i + 2) + { + written = snprintf(pos, len, "%s%x", first ? "" : ":", + 256*address.ptr[i] + address.ptr[i+1]); + if (written < 0 || written > len) + { + break; + } + pos += written; + len -= written; + first = FALSE; + } + } + else + { + snprintf(buf, BUF_LEN, "%H", host); + } + attr = axiom_attribute_create(this->env, "value", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + attr = axiom_attribute_create(this->env, "type", + host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create a device + */ +static axiom_node_t* create_device(private_tnc_ifmap_soap_t *this) +{ + axiom_element_t *el; + axiom_node_t *node, *node2, *node3; + axiom_text_t *text; + + el = axiom_element_create(this->env, NULL, "device", NULL, &node); + el = axiom_element_create(this->env, NULL, "name", NULL, &node2); + axiom_node_add_child(node, this->env, node2); + text = axiom_text_create(this->env, node2, this->device_name, &node3); + + return node; +} + +/** + * Create metadata + */ +static axiom_node_t* create_metadata(private_tnc_ifmap_soap_t *this, + char *metadata) +{ + axiom_element_t *el; + axiom_node_t *node, *node2; + axiom_attribute_t *attr; + axiom_namespace_t *ns_meta; + + el = axiom_element_create(this->env, NULL, "metadata", NULL, &node); + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + + el = axiom_element_create(this->env, NULL, metadata, ns_meta, &node2); + axiom_node_add_child(node, this->env, node2); + attr = axiom_attribute_create(this->env, "ifmap-cardinality", "singleValue", + NULL); + axiom_element_add_attribute(el, this->env, attr, node2); + + return node; +} + +/** + * Create capability metadata + */ +static axiom_node_t* create_capability(private_tnc_ifmap_soap_t *this, + identification_t *name) +{ + axiom_element_t *el; + axiom_node_t *node, *node2, *node3; + axiom_namespace_t *ns_meta; + axiom_attribute_t *attr; + axiom_text_t *text; + char buf[BUF_LEN]; + + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + el = axiom_element_create(this->env, NULL, "capability", ns_meta, &node); + attr = axiom_attribute_create(this->env, "ifmap-cardinality", "multiValue", + NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + el = axiom_element_create(this->env, NULL, "name", NULL, &node2); + axiom_node_add_child(node, this->env, node2); + snprintf(buf, BUF_LEN, "%Y", name); + text = axiom_text_create(this->env, node2, buf, &node3); + + el = axiom_element_create(this->env, NULL, "administrative-domain", NULL, &node2); + axiom_node_add_child(node, this->env, node2); + text = axiom_text_create(this->env, node2, "strongswan", &node3); + + return node; +} + +/** + * Create enforcement-report metadata + */ +static axiom_node_t* create_enforcement_report(private_tnc_ifmap_soap_t *this, + char *action, char *reason) +{ + axiom_element_t *el; + axiom_node_t *node, *node2, *node3, *node4; + axiom_namespace_t *ns_meta; + axiom_attribute_t *attr; + axiom_text_t *text; + + el = axiom_element_create(this->env, NULL, "metadata", NULL, &node); + + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + el = axiom_element_create(this->env, NULL, "enforcement-report", ns_meta, + &node2); + attr = axiom_attribute_create(this->env, "ifmap-cardinality", + "multiValue", NULL); + axiom_element_add_attribute(el, this->env, attr, node2); + axiom_node_add_child(node, this->env, node2); + + el = axiom_element_create(this->env, NULL, "enforcement-action", NULL, + &node3); + axiom_node_add_child(node2, this->env, node3); + text = axiom_text_create(this->env, node3, action, &node4); + + el = axiom_element_create(this->env, NULL, "enforcement-reason", NULL, + &node3); + axiom_node_add_child(node2, this->env, node3); + text = axiom_text_create(this->env, node3, reason, &node4); + + return node; +} + +/** + * Create delete filter + */ +static axiom_node_t* create_delete_filter(private_tnc_ifmap_soap_t *this, + char *metadata) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN]; + + el = axiom_element_create(this->env, NULL, "delete", NULL, &node); + + snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']", + metadata, this->ifmap_publisher_id); + attr = axiom_attribute_create(this->env, "filter", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create a publish request + */ +static axiom_node_t* create_publish_request(private_tnc_ifmap_soap_t *this) +{ + axiom_element_t *el; + axiom_node_t *request; + axiom_namespace_t *ns, *ns_meta; + axiom_attribute_t *attr; + + ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); + el = axiom_element_create(this->env, NULL, "publish", ns, &request); + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + axiom_element_declare_namespace(el, this->env, request, ns_meta); + attr = axiom_attribute_create(this->env, "session-id", this->session_id, + NULL); + axiom_element_add_attribute(el, this->env, attr, request); + + return request; +} + +METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool, + private_tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, bool up) +{ + axiom_node_t *request, *node, *node2; + axiom_element_t *el; + + enumerator_t *e1, *e2; + auth_rule_t type; + identification_t *id, *eap_id, *group; + host_t *host; + auth_cfg_t *auth; + u_int32_t ike_sa_id; + bool is_user = FALSE, first = TRUE; + + /* extract relevant data from IKE_SA*/ + ike_sa_id = ike_sa->get_unique_id(ike_sa); + id = ike_sa->get_other_id(ike_sa); + eap_id = ike_sa->get_other_eap_id(ike_sa); + host = ike_sa->get_other_host(ike_sa); + + /* in the presence of an EAP Identity, treat it as a username */ + if (!id->equals(id, eap_id)) + { + is_user = TRUE; + id = eap_id; + } + + /* build publish request */ + request = create_publish_request(this); + + /* delete any existing enforcement reports */ + if (up) + { + node = create_delete_filter(this, "enforcement-report"); + axiom_node_add_child(request, this->env, node); + axiom_node_add_child(node, this->env, + create_ip_address(this, host)); + axiom_node_add_child(node, this->env, + create_device(this)); + } + + /** + * update or delete authenticated-as metadata + */ + if (up) + { + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + } + else + { + node = create_delete_filter(this, "authenticated-as"); + } + axiom_node_add_child(request, this->env, node); + + /* add access-request, identity and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_identity(this, id, is_user)); + if (up) + { + axiom_node_add_child(node, this->env, + create_metadata(this, "authenticated-as")); + } + + /** + * update or delete access-request-ip metadata + */ + if (up) + { + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + } + else + { + node = create_delete_filter(this, "access-request-ip"); + } + axiom_node_add_child(request, this->env, node); + + /* add access-request, ip-address and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_ip_address(this, host)); + if (up) + { + axiom_node_add_child(node, this->env, + create_metadata(this, "access-request-ip")); + } + + /** + * update or delete authenticated-by metadata + */ + if (up) + { + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + } + else + { + node = create_delete_filter(this, "authenticated-by"); + } + axiom_node_add_child(request, this->env, node); + + /* add access-request, device and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_device(this)); + if (up) + { + axiom_node_add_child(node, this->env, + create_metadata(this, "authenticated-by")); + } + + /** + * update or delete capability metadata + */ + e1 = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE); + while (e1->enumerate(e1, &auth)) + { + e2 = auth->create_enumerator(auth); + while (e2->enumerate(e2, &type, &group)) + { + /* look for group memberships */ + if (type == AUTH_RULE_GROUP) + { + if (first) + { + first = FALSE; + + if (up) + { + el = axiom_element_create(this->env, NULL, "update", + NULL, &node); + } + else + { + node = create_delete_filter(this, "capability"); + } + axiom_node_add_child(request, this->env, node); + + /* add access-request */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + if (!up) + { + break; + } + el = axiom_element_create(this->env, NULL, "metadata", NULL, + &node2); + axiom_node_add_child(node, this->env, node2); + } + axiom_node_add_child(node2, this->env, + create_capability(this, group)); + } + if (!first && !up) + { + break; + } + } + e2->destroy(e2); + } + e1->destroy(e1); + + /* send publish request and receive publishReceived */ + return send_receive(this, "publish", request, "publishReceived", NULL); +} + +METHOD(tnc_ifmap_soap_t, publish_device_ip, bool, + private_tnc_ifmap_soap_t *this, host_t *host) +{ + axiom_node_t *request, *node; + axiom_element_t *el; + + /* build publish update request */ + request = create_publish_request(this); + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + axiom_node_add_child(request, this->env, node); + + /* add device, ip-address and metadata */ + axiom_node_add_child(node, this->env, + create_device(this)); + axiom_node_add_child(node, this->env, + create_ip_address(this, host)); + axiom_node_add_child(node, this->env, + create_metadata(this, "device-ip")); + + /* send publish request and receive publishReceived */ + return send_receive(this, "publish", request, "publishReceived", NULL); +} + +METHOD(tnc_ifmap_soap_t, publish_enforcement_report, bool, + private_tnc_ifmap_soap_t *this, host_t *host, char *action, char *reason) +{ + axiom_node_t *request, *node; + axiom_element_t *el; + + /* build publish update request */ + request = create_publish_request(this); + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + axiom_node_add_child(request, this->env, node); + + /* add ip-address and metadata */ + axiom_node_add_child(node, this->env, + create_ip_address(this, host)); + axiom_node_add_child(node, this->env, + create_device(this)); + axiom_node_add_child(node, this->env, + create_enforcement_report(this, action, reason)); + + /* send publish request and receive publishReceived */ + return send_receive(this, "publish", request, "publishReceived", NULL); +} + +METHOD(tnc_ifmap_soap_t, endSession, bool, + private_tnc_ifmap_soap_t *this) +{ + axiom_node_t *request; + axiom_element_t *el; + axiom_namespace_t *ns; + axiom_attribute_t *attr; + + /* build endSession request */ + ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); + el = axiom_element_create(this->env, NULL, "endSession", ns, &request); + attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL); + axiom_element_add_attribute(el, this->env, attr, request); + + /* send endSession request and receive end SessionResult */ + return send_receive(this, "endSession", request, "endSessionResult", NULL); +} + +METHOD(tnc_ifmap_soap_t, destroy, void, + private_tnc_ifmap_soap_t *this) +{ + if (this->session_id) + { + endSession(this); + free(this->session_id); + free(this->ifmap_publisher_id); + free(this->device_name); + } + if (this->svc_client) + { + axis2_svc_client_free(this->svc_client, this->env); + } + if (this->env) + { + axutil_env_free(this->env); + } + free(this); +} + +static bool axis2c_init(private_tnc_ifmap_soap_t *this) +{ + axis2_char_t *server, *server_cert, *key_file, *client_home; + axis2_char_t *ssl_passphrase, *username, *password; + axis2_endpoint_ref_t* endpoint_ref = NULL; + axis2_options_t *options = NULL; + axis2_transport_in_desc_t *transport_in; + axis2_transport_out_desc_t *transport_out; + axis2_transport_sender_t *transport_sender; + axutil_property_t* property; + + /* Getting configuration parameters from strongswan.conf */ + client_home = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.client_home", + AXIS2_GETENV("AXIS2C_HOME")); + server = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.server", IFMAP_SERVER); + server_cert = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.server_cert", NULL); + key_file = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.key_file", NULL); + ssl_passphrase = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.ssl_passphrase", NULL); + username = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.username", NULL); + password = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.password", NULL); + + if (!server_cert) + { + DBG1(DBG_TNC, "MAP server certificate not defined"); + return FALSE; + } + + if (!key_file && (!username || !password)) + { + DBG1(DBG_TNC, "MAP client keyfile or %s%s%s not defined", + (!username) ? "username" : "", + (!username && ! password) ? " and " : "", + (!password) ? "password" : ""); + return FALSE; + } + + /* Create Axis2/C environment and options */ + this->env = axutil_env_create_all(IFMAP_LOGFILE, AXIS2_LOG_LEVEL_TRACE); + options = axis2_options_create(this->env); + + /* Set path to the MAP server certificate */ + property =axutil_property_create_with_args(this->env, 0, 0, 0, + server_cert); + axis2_options_set_property(options, this->env, + AXIS2_SSL_SERVER_CERT, property); + + if (key_file) + { + /* Set path to the MAP client certificate */ + property =axutil_property_create_with_args(this->env, 0, 0, 0, + key_file); + axis2_options_set_property(options, this->env, + AXIS2_SSL_KEY_FILE, property); + if (ssl_passphrase) + { + /* Provide SSL passphrase */ + property =axutil_property_create_with_args(this->env, 0, 0, 0, + ssl_passphrase); + axis2_options_set_property(options, this->env, + AXIS2_SSL_PASSPHRASE, property); + } + } + else + { + /* Set up HTTP Basic MAP client authentication */ + axis2_options_set_http_auth_info(options, this->env, + username, password, "Basic"); + } + + /* Define the MAP server as the to endpoint reference */ + endpoint_ref = axis2_endpoint_ref_create(this->env, server); + axis2_options_set_to(options, this->env, endpoint_ref); + + /* Set up https transport */ + transport_in = axis2_transport_in_desc_create(this->env, + AXIS2_TRANSPORT_ENUM_HTTPS); + transport_out = axis2_transport_out_desc_create(this->env, + AXIS2_TRANSPORT_ENUM_HTTPS); + transport_sender = axis2_http_transport_sender_create(this->env); + axis2_transport_out_desc_set_sender(transport_out, this->env, + transport_sender); + axis2_options_set_transport_in(options, this->env, transport_in); + axis2_options_set_transport_out(options, this->env, transport_out); + + /* Create the axis2 service client */ + this->svc_client = axis2_svc_client_create(this->env, client_home); + if (!this->svc_client) + { + DBG1(DBG_TNC, "could not create axis2 service client"); + AXIS2_LOG_ERROR(this->env->log, AXIS2_LOG_SI, + "Stub invoke FAILED: Error code: %d :: %s", + this->env->error->error_number, + AXIS2_ERROR_GET_MESSAGE(this->env->error)); + destroy(this); + return FALSE; + } + + axis2_svc_client_set_options(this->svc_client, this->env, options); + DBG1(DBG_TNC, "connecting as MAP client '%s' to MAP server at '%s'", + username, server); + + return TRUE; +} + +/** + * See header + */ +tnc_ifmap_soap_t *tnc_ifmap_soap_create() +{ + private_tnc_ifmap_soap_t *this; + + INIT(this, + .public = { + .newSession = _newSession, + .purgePublisher = _purgePublisher, + .publish_ike_sa = _publish_ike_sa, + .publish_device_ip = _publish_device_ip, + .publish_enforcement_report = _publish_enforcement_report, + .endSession = _endSession, + .destroy = _destroy, + }, + ); + + if (!axis2c_init(this)) + { + destroy(this); + return NULL; + } + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h new file mode 100644 index 000000000..4bf421e33 --- /dev/null +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h @@ -0,0 +1,95 @@ +/* + * 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_ifmap_soap tnc_ifmap_soap + * @{ @ingroup tnc_ifmap + */ + +#ifndef TNC_IFMAP_SOAP_H_ +#define TNC_IFMAP_SOAP_H_ + +#include <library.h> +#include <utils/host.h> +#include <sa/ike_sa.h> + +typedef struct tnc_ifmap_soap_t tnc_ifmap_soap_t; + +/** + * Implements the TNC IF-MAP 2.0 SOAP Binding + */ +struct tnc_ifmap_soap_t { + + /** + * Creates a new IF-MAP session + * + * @return TRUE if command was successful + */ + bool (*newSession)(tnc_ifmap_soap_t *this); + + /** + * Purges all metadata published by this publisher + * + * @return TRUE if command was successful + */ + bool (*purgePublisher)(tnc_ifmap_soap_t *this); + + /** + * Publish metadata about established/deleted IKE_SAs + * + * @param ike_sa IKE_SA for which metadate is published + * @param up TRUE if IKE_SEA is up, FALSE if down + * @return TRUE if command was successful + */ + bool (*publish_ike_sa)(tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, bool up); + + /** + * Publish PEP device-ip metadata + * + * @param host IP address of local endpoint + * @return TRUE if command was successful + */ + bool (*publish_device_ip)(tnc_ifmap_soap_t *this, host_t *host); + + /** + * Publish enforcement-report metadata + * + * @param host Host to be enforced + * @param action Enforcement action ("block" or "quarantine") + * @param reason Enforcement reason + * @return TRUE if command was successful + */ + bool (*publish_enforcement_report)(tnc_ifmap_soap_t *this, host_t *host, + char *action, char *reason); + + /** + * Ends an IF-MAP session + * + * @return TRUE if command was successful + */ + bool (*endSession)(tnc_ifmap_soap_t *this); + + /** + * Destroy a tnc_ifmap_soap_t. + */ + void (*destroy)(tnc_ifmap_soap_t *this); +}; + +/** + * Create a tnc_ifmap_soap instance. + */ +tnc_ifmap_soap_t *tnc_ifmap_soap_create(); + +#endif /** TNC_IFMAP_SOAP_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am index 2c551813e..fc1979525 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.am +++ b/src/libcharon/plugins/tnc_imc/Makefile.am @@ -1,6 +1,8 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @@ -8,6 +10,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnc-imc.la else plugin_LTLIBRARIES = libstrongswan-tnc-imc.la +libstrongswan_tnc_imc_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_tnc_imc_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnc_imc/Makefile.in b/src/libcharon/plugins/tnc_imc/Makefile.in index c2bc35dc5..550c0516c 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.in +++ b/src/libcharon/plugins/tnc_imc/Makefile.in @@ -74,7 +74,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnc_imc_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_tnc_imc_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la am_libstrongswan_tnc_imc_la_OBJECTS = tnc_imc_plugin.lo tnc_imc.lo \ tnc_imc_manager.lo tnc_imc_bind_function.lo libstrongswan_tnc_imc_la_OBJECTS = \ @@ -194,6 +196,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +207,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +224,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +274,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -276,12 +285,18 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imc.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imc.la +@MONOLITHIC_FALSE@libstrongswan_tnc_imc_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + libstrongswan_tnc_imc_la_SOURCES = \ tnc_imc_plugin.h tnc_imc_plugin.c tnc_imc.h tnc_imc.c \ tnc_imc_manager.h tnc_imc_manager.c tnc_imc_bind_function.c diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c index d7fc2c65d..a1f2d770f 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Mike McCauley - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-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 @@ -17,8 +18,11 @@ #include <dlfcn.h> +#include <tncif_pa_subtypes.h> + #include <debug.h> #include <library.h> +#include <utils/linked_list.h> #include <threading/mutex.h> typedef struct private_tnc_imc_t private_tnc_imc_t; @@ -54,9 +58,19 @@ struct private_tnc_imc_t { TNC_IMCID id; /** - * List of message types supported by IMC + * list of additional IMC IDs */ - TNC_MessageTypeList supported_types; + linked_list_t *additional_ids; + + /** + * List of message types supported by IMC - Vendor ID part + */ + TNC_VendorIDList supported_vids; + + /** + * List of message types supported by IMC - Subtype part + */ + TNC_MessageSubtypeList supported_subtypes; /** * Number of supported message types @@ -81,6 +95,54 @@ METHOD(imc_t, get_id, TNC_IMCID, return this->id; } +METHOD(imc_t, add_id, void, + private_tnc_imc_t *this, TNC_IMCID id) +{ + void *pointer; + + /* store the scalar value in the pointer */ + pointer = (void*)id; + this->additional_ids->insert_last(this->additional_ids, pointer); +} + +METHOD(imc_t, has_id, bool, + private_tnc_imc_t *this, TNC_IMCID id) +{ + enumerator_t *enumerator; + TNC_IMCID additional_id; + void *pointer; + bool found = FALSE; + + /* check primary IMC ID */ + if (id == this->id) + { + return TRUE; + } + + /* return if there are no additional IMC IDs */ + if (this->additional_ids->get_count(this->additional_ids) == 0) + { + return FALSE; + } + + /* check additional IMC IDs */ + enumerator = this->additional_ids->create_enumerator(this->additional_ids); + while (enumerator->enumerate(enumerator, &pointer)) + { + /* interpret pointer as scalar value */ + additional_id = (TNC_UInt32)pointer; + + if (id == additional_id) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + METHOD(imc_t, get_name, char*, private_tnc_imc_t *this) { @@ -91,66 +153,150 @@ METHOD(imc_t, set_message_types, void, private_tnc_imc_t *this, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { - char buf[512]; + char buf[BUF_LEN]; char *pos = buf; int len = sizeof(buf); - int written; + int i, written; + size_t size; + TNC_VendorID vid; + TNC_MessageSubtype subtype; + enum_name_t *pa_subtype_names; /* lock the imc_t instance */ this->mutex->lock(this->mutex); - /* Free an existing MessageType list */ - free(this->supported_types); - this->supported_types = NULL; + /* Free existing VendorID and MessageSubtype lists */ + free(this->supported_vids); + this->supported_vids = NULL; + free(this->supported_subtypes); + this->supported_subtypes = NULL; /* Store the new MessageType list */ this->type_count = type_count; if (type_count && supported_types) { - size_t size = type_count * sizeof(TNC_MessageType); - int i; + size = type_count * sizeof(TNC_VendorID); + this->supported_vids = malloc(size); + size = type_count * sizeof(TNC_MessageSubtype); + this->supported_subtypes = malloc(size); for (i = 0; i < type_count; i++) { - written = snprintf(pos, len, " 0x%08x", supported_types[i]); + vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY; + subtype = supported_types[i] & TNC_SUBTYPE_ANY; + + pa_subtype_names = get_pa_subtype_names(vid); + if (pa_subtype_names) + { + written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x", + pen_names, vid, pa_subtype_names, subtype, + vid, subtype); + } + else + { + written = snprintf(pos, len," '%N' 0x%06x/0x%02x", + pen_names, vid, vid, subtype); + } if (written >= len) { break; } pos += written; len -= written; + + this->supported_vids[i] = vid; + this->supported_subtypes[i] = subtype; } - this->supported_types = malloc(size); - memcpy(this->supported_types, supported_types, size); } *pos = '\0'; - DBG2(DBG_TNC, "IMC %u supports %u message types:%s", - this->id, type_count, buf); + DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s", + this->id, type_count, (type_count == 1) ? "":"s", buf); + + /* unlock the imc_t instance */ + this->mutex->unlock(this->mutex); +} + +METHOD(imc_t, set_message_types_long, void, + private_tnc_imc_t *this, TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count) +{ + char buf[BUF_LEN]; + char *pos = buf; + int len = sizeof(buf); + int i, written; + size_t size; + TNC_VendorID vid; + TNC_MessageSubtype subtype; + enum_name_t *pa_subtype_names; /* lock the imc_t instance */ + this->mutex->lock(this->mutex); + + /* Free existing VendorID and MessageSubtype lists */ + free(this->supported_vids); + this->supported_vids = NULL; + free(this->supported_subtypes); + this->supported_subtypes = NULL; + + /* Store the new MessageType list */ + this->type_count = type_count; + if (type_count && supported_vids && supported_subtypes) + { + size = type_count * sizeof(TNC_VendorID); + this->supported_vids = malloc(size); + memcpy(this->supported_vids, supported_vids, size); + size = type_count * sizeof(TNC_MessageSubtype); + this->supported_subtypes = malloc(size); + memcpy(this->supported_subtypes, supported_subtypes, size); + + for (i = 0; i < type_count; i++) + { + vid = supported_vids[i]; + subtype = supported_subtypes[i]; + + pa_subtype_names = get_pa_subtype_names(vid); + if (pa_subtype_names) + { + written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x", + pen_names, vid, pa_subtype_names, subtype, + vid, subtype); + } + else + { + written = snprintf(pos, len," '%N' 0x%06x/0x%08x", + pen_names, vid, vid, subtype); + } + if (written >= len) + { + break; + } + pos += written; + len -= written; + } + } + *pos = '\0'; + DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s", + this->id, type_count, (type_count == 1) ? "":"s", buf); + + /* unlock the imc_t instance */ this->mutex->unlock(this->mutex); } METHOD(imc_t, type_supported, bool, - private_tnc_imc_t *this, TNC_MessageType message_type) + private_tnc_imc_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype) { - TNC_VendorID msg_vid, vid; - TNC_MessageSubtype msg_subtype, subtype; + TNC_VendorID vid; + TNC_MessageSubtype subtype; int i; - msg_vid = (message_type >> 8) & TNC_VENDORID_ANY; - msg_subtype = message_type & TNC_SUBTYPE_ANY; - for (i = 0; i < this->type_count; i++) { - vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY; - subtype = this->supported_types[i] & TNC_SUBTYPE_ANY; - - if (this->supported_types[i] == message_type - || (subtype == TNC_SUBTYPE_ANY - && (msg_vid == vid || vid == TNC_VENDORID_ANY)) - || (vid == TNC_VENDORID_ANY - && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY))) + vid = this->supported_vids[i]; + subtype = this->supported_subtypes[i]; + + if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) || + (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY || + subtype == msg_subtype))) { return TRUE; } @@ -163,7 +309,9 @@ METHOD(imc_t, destroy, void, { dlclose(this->handle); this->mutex->destroy(this->mutex); - free(this->supported_types); + this->additional_ids->destroy(this->additional_ids); + free(this->supported_vids); + free(this->supported_subtypes); free(this->name); free(this->path); free(this); @@ -180,13 +328,17 @@ imc_t* tnc_imc_create(char *name, char *path) .public = { .set_id = _set_id, .get_id = _get_id, + .add_id = _add_id, + .has_id = _has_id, .get_name = _get_name, .set_message_types = _set_message_types, + .set_message_types_long = _set_message_types_long, .type_supported = _type_supported, .destroy = _destroy, }, .name = name, .path = path, + .additional_ids = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); @@ -220,6 +372,8 @@ imc_t* tnc_imc_create(char *name, char *path) } this->public.receive_message = dlsym(this->handle, "TNC_IMC_ReceiveMessage"); + this->public.receive_message_long = + dlsym(this->handle, "TNC_IMC_ReceiveMessageLong"); this->public.batch_ending = dlsym(this->handle, "TNC_IMC_BatchEnding"); this->public.terminate = diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c index 25a6a1cc4..90a607ccc 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c @@ -13,12 +13,11 @@ * for more details. */ -#include "tnc_imc.h" +#include <tnc/tnc.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/tnccs/tnccs_manager.h> #include <debug.h> -#include <daemon.h> - -#define TNC_IMVID_ANY 0xffff /** * Called by the IMC to inform a TNCC about the set of message types the IMC @@ -28,14 +27,33 @@ TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { - if (!charon->imcs->is_registered(charon->imcs, imc_id)) + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) { DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMC %u", imc_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->imcs->set_message_types(charon->imcs, imc_id, - supported_types, type_count); + return tnc->imcs->set_message_types(tnc->imcs, imc_id, supported_types, + type_count); +} + +/** + * Called by the IMC to inform a TNCC about the set of message types the IMC + * is able to receive. This function supports long message types. + */ +TNC_Result TNC_TNCC_ReportMessageTypesLong(TNC_IMCID imc_id, + TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, + TNC_UInt32 type_count) +{ + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring ReportMessageTypesLong() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } + return tnc->imcs->set_message_types_long(tnc->imcs, imc_id, supported_vids, + supported_subtypes, type_count); } /** @@ -45,14 +63,14 @@ TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id, TNC_ConnectionID connection_id, TNC_RetryReason reason) { - if (!charon->imcs->is_registered(charon->imcs, imc_id)) + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) { DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMC %u", imc_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->request_handshake_retry(charon->tnccs, TRUE, imc_id, - connection_id, reason); + return tnc->tnccs->request_handshake_retry(tnc->tnccs, TRUE, imc_id, + connection_id, reason); } /** @@ -64,14 +82,97 @@ TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id, TNC_UInt32 msg_len, TNC_MessageType msg_type) { - if (!charon->imcs->is_registered(charon->imcs, imc_id)) + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } + msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + return tnc->tnccs->send_message(tnc->tnccs, imc_id, TNC_IMVID_ANY, + connection_id, 0, msg, msg_len, msg_vid, msg_subtype); +} + +/** + * Called by the IMC when an IMC-IMV message is to be sent over IF-TNCCS 2.0 + */ +TNC_Result TNC_TNCC_SendMessageLong(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 imv_id) +{ + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) { DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u", imc_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->send_message(charon->tnccs, imc_id, TNC_IMVID_ANY, - connection_id, msg, msg_len, msg_type); + return tnc->tnccs->send_message(tnc->tnccs, imc_id, imv_id, connection_id, + msg_flags, msg, msg_len, msg_vid, msg_subtype); +} + +/** + * Called by the IMC to get the value of an attribute associated with a + * connection or with the TNCC as a whole. + */ +TNC_Result TNC_TNCC_GetAttribute(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *out_value_len) +{ + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } + return tnc->tnccs->get_attribute(tnc->tnccs, TRUE, imc_id, connection_id, + attribute_id, buffer_len, buffer, out_value_len); +} + +/** + * Called by the IMC to set the value of an attribute associated with a + * connection or with the TNCC as a whole. + */ +TNC_Result TNC_TNCC_SetAttribute(TNC_IMCID imc_id, + TNC_ConnectionID connection_id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer) +{ + if (!tnc->imcs->is_registered(tnc->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } + return tnc->tnccs->set_attribute(tnc->tnccs, TRUE, imc_id, connection_id, + attribute_id, buffer_len, buffer); +} + +/** + * Called by the IMC when it wants to reserve an additional IMC ID for itself + */ +TNC_Result TNC_TNCC_ReserveAdditionalIMCID(TNC_IMCID imc_id, TNC_UInt32 *new_id) +{ + if (tnc->imcs->reserve_id(tnc->imcs, imc_id, new_id)) + { + return TNC_RESULT_SUCCESS; + } + DBG1(DBG_TNC, "ignoring ReserveAdditionalIMCID() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; } /** @@ -85,6 +186,10 @@ TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id, { *function_pointer = (void*)TNC_TNCC_ReportMessageTypes; } + else if (streq(function_name, "TNC_TNCC_ReportMessageTypesLong")) + { + *function_pointer = (void*)TNC_TNCC_ReportMessageTypesLong; + } else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry")) { *function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry; @@ -93,6 +198,22 @@ TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id, { *function_pointer = (void*)TNC_TNCC_SendMessage; } + else if (streq(function_name, "TNC_TNCC_SendMessageLong")) + { + *function_pointer = (void*)TNC_TNCC_SendMessageLong; + } + else if (streq(function_name, "TNC_TNCC_GetAttribute")) + { + *function_pointer = (void*)TNC_TNCC_GetAttribute; + } + else if (streq(function_name, "TNC_TNCC_SetAttribute")) + { + *function_pointer = (void*)TNC_TNCC_SetAttribute; + } + else if (streq(function_name, "TNC_TNCC_ReserveAdditionalIMCID")) + { + *function_pointer = (void*)TNC_TNCC_ReserveAdditionalIMCID; + } else { return TNC_RESULT_INVALID_PARAMETER; diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c index ccf6aea67..e101cf974 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Mike McCauley - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-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 @@ -14,13 +15,12 @@ */ #include "tnc_imc_manager.h" +#include "tnc_imc.h" -#include <tnc/imc/imc_manager.h> -#include <tnc/tncifimc.h> +#include <tncifimc.h> -#include <debug.h> -#include <library.h> #include <utils/linked_list.h> +#include <debug.h> typedef struct private_tnc_imc_manager_t private_tnc_imc_manager_t; @@ -94,6 +94,33 @@ METHOD(imc_manager_t, remove_, imc_t*, return removed_imc; } +METHOD(imc_manager_t, load, bool, + private_tnc_imc_manager_t *this, char *name, char *path) +{ + imc_t *imc; + + imc = tnc_imc_create(name, path); + if (!imc) + { + free(name); + free(path); + return FALSE; + } + if (!add(this, imc)) + { + if (imc->terminate && + imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully", + imc->get_name(imc)); + } + imc->destroy(imc); + return FALSE; + } + DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), name, path); + return TRUE; +} + METHOD(imc_manager_t, is_registered, bool, private_tnc_imc_manager_t *this, TNC_IMCID id) { @@ -104,9 +131,34 @@ METHOD(imc_manager_t, is_registered, bool, enumerator = this->imcs->create_enumerator(this->imcs); while (enumerator->enumerate(enumerator, &imc)) { - if (id == imc->get_id(imc)) + if (imc->has_id(imc, id)) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + +METHOD(imc_manager_t, reserve_id, bool, + private_tnc_imc_manager_t *this, TNC_IMCID id, TNC_UInt32 *new_id) +{ + enumerator_t *enumerator; + imc_t *imc; + bool found = FALSE; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (imc->get_id(imc)) { found = TRUE; + *new_id = this->next_imc_id++; + imc->add_id(imc, *new_id); + DBG2(DBG_TNC, "additional ID %u reserved for IMC with primary ID %u", + *new_id, id); break; } } @@ -177,30 +229,77 @@ METHOD(imc_manager_t, set_message_types, TNC_Result, return result; } +METHOD(imc_manager_t, set_message_types_long, TNC_Result, + private_tnc_imc_manager_t *this, TNC_IMCID id, + TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, + TNC_UInt32 type_count) +{ + enumerator_t *enumerator; + imc_t *imc; + TNC_Result result = TNC_RESULT_FATAL; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (id == imc->get_id(imc)) + { + imc->set_message_types_long(imc, supported_vids, supported_subtypes, + type_count); + result = TNC_RESULT_SUCCESS; + break; + } + } + enumerator->destroy(enumerator); + return result; +} + METHOD(imc_manager_t, receive_message, void, private_tnc_imc_manager_t *this, TNC_ConnectionID connection_id, - TNC_BufferReference message, - TNC_UInt32 message_len, - TNC_MessageType message_type) + bool excl, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imv_id, + TNC_UInt32 dst_imc_id) { bool type_supported = FALSE; + TNC_MessageType msg_type; + TNC_UInt32 msg_flags; enumerator_t *enumerator; imc_t *imc; enumerator = this->imcs->create_enumerator(this->imcs); while (enumerator->enumerate(enumerator, &imc)) { - if (imc->receive_message && imc->type_supported(imc, message_type)) + if (imc->type_supported(imc, msg_vid, msg_subtype) && + (!excl || (excl && imc->has_id(imc, dst_imc_id)) )) { - type_supported = TRUE; - imc->receive_message(imc->get_id(imc), connection_id, - message, message_len, message_type); + if (imc->receive_message_long && src_imv_id) + { + type_supported = TRUE; + msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + imc->receive_message_long(imc->get_id(imc), connection_id, + msg_flags, msg, msg_len, msg_vid, msg_subtype, + src_imv_id, dst_imc_id); + + } + else if (imc->receive_message && msg_vid <= TNC_VENDORID_ANY && + msg_subtype <= TNC_SUBTYPE_ANY) + { + type_supported = TRUE; + msg_type = (msg_vid << 8) | msg_subtype; + imc->receive_message(imc->get_id(imc), connection_id, + msg, msg_len, msg_type); + } } } enumerator->destroy(enumerator); if (!type_supported) { - DBG2(DBG_TNC, "message type 0x%08x not supported by any IMC", message_type); + DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMC", + msg_vid, msg_subtype); } } @@ -251,11 +350,14 @@ imc_manager_t* tnc_imc_manager_create(void) .public = { .add = _add, .remove = _remove_, /* avoid name conflict with stdio.h */ + .load = _load, .is_registered = _is_registered, + .reserve_id = _reserve_id, .get_preferred_language = _get_preferred_language, .notify_connection_change = _notify_connection_change, .begin_handshake = _begin_handshake, .set_message_types = _set_message_types, + .set_message_types_long = _set_message_types_long, .receive_message = _receive_message, .batch_ending = _batch_ending, .destroy = _destroy, diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c index bc13b8735..a25b1843c 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2011 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,180 +15,63 @@ #include "tnc_imc_plugin.h" #include "tnc_imc_manager.h" -#include "tnc_imc.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> +#include <tnc/tnc.h> -#include <daemon.h> -#include <utils/lexparser.h> +typedef struct private_tnc_imc_plugin_t private_tnc_imc_plugin_t; /** - * load IMCs from a configuration file + * Private data of a tnc_imc_plugin_t object. */ -static bool load_imcs(char *filename) -{ - int fd, line_nr = 0; - chunk_t src, line; - struct stat sb; - void *addr; - - DBG1(DBG_TNC, "loading IMCs from '%s'", filename); - fd = open(filename, O_RDONLY); - if (fd == -1) - { - DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, - strerror(errno)); - return FALSE; - } - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, - strerror(errno)); - close(fd); - return FALSE; - } - addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); - close(fd); - return FALSE; - } - src = chunk_create(addr, sb.st_size); - - while (fetchline(&src, &line)) - { - char *name, *path; - chunk_t token; - imc_t *imc; - - line_nr++; - - /* skip comments or empty lines */ - if (*line.ptr == '#' || !eat_whitespace(&line)) - { - continue; - } - - /* determine keyword */ - if (!extract_token(&token, ' ', &line)) - { - DBG1(DBG_TNC, "line %d: keyword must be followed by a space", - line_nr); - return FALSE; - } - - /* only interested in IMCs */ - if (!match("IMC", &token)) - { - continue; - } - - /* advance to the IMC name and extract it */ - if (!extract_token(&token, '"', &line) || - !extract_token(&token, '"', &line)) - { - DBG1(DBG_TNC, "line %d: IMC name must be set in double quotes", - line_nr); - return FALSE; - } +struct private_tnc_imc_plugin_t { - /* copy the IMC name */ - name = malloc(token.len + 1); - memcpy(name, token.ptr, token.len); - name[token.len] = '\0'; - - /* advance to the IMC path and extract it */ - if (!eat_whitespace(&line)) - { - DBG1(DBG_TNC, "line %d: IMC path is missing", line_nr); - free(name); - return FALSE; - } - if (!extract_token(&token, ' ', &line)) - { - token = line; - } - - /* copy the IMC path */ - path = malloc(token.len + 1); - memcpy(path, token.ptr, token.len); - path[token.len] = '\0'; - - /* load and register IMC instance */ - imc = tnc_imc_create(name, path); - if (!imc) - { - free(name); - free(path); - return FALSE; - } - if (!charon->imcs->add(charon->imcs, imc)) - { - if (imc->terminate && - imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS) - { - DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully", - imc->get_name(imc)); - } - imc->destroy(imc); - return FALSE; - } - DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), - name, path); - } - munmap(addr, sb.st_size); - close(fd); - return TRUE; -} + /** + * Public interface. + */ + tnc_imc_plugin_t public; +}; METHOD(plugin_t, get_name, char*, - tnc_imc_plugin_t *this) + private_tnc_imc_plugin_t *this) { return "tnc-imc"; } +METHOD(plugin_t, get_features, int, + private_tnc_imc_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create), + PLUGIN_PROVIDE(CUSTOM, "imc-manager"), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, - tnc_imc_plugin_t *this) + private_tnc_imc_plugin_t *this) { - charon->imcs->destroy(charon->imcs); free(this); } /* * see header file */ -plugin_t *tnc_imc_plugin_create() +plugin_t *tnc_imc_plugin_create(void) { - char *tnc_config; - tnc_imc_plugin_t *this; + private_tnc_imc_plugin_t *this; INIT(this, - .plugin = { - .get_name = _get_name, - .reload = (void*)return_false, - .destroy = _destroy, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, }, ); - /* Create IMC manager */ - charon->imcs = tnc_imc_manager_create(); - - /* Load IMCs and abort if not all instances initalize successfully */ - tnc_config = lib->settings->get_str(lib->settings, - "charon.plugins.tnc-imc.tnc_config", "/etc/tnc_config"); - if (!load_imcs(tnc_config)) - { - charon->imcs->destroy(charon->imcs); - charon->imcs = NULL; - free(this); - return NULL; - } - return &this->plugin; + return &this->public.plugin; } diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am index 3ba283bb7..eca3b377b 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.am +++ b/src/libcharon/plugins/tnc_imv/Makefile.am @@ -1,6 +1,10 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @@ -8,6 +12,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnc-imv.la else plugin_LTLIBRARIES = libstrongswan-tnc-imv.la +libstrongswan_tnc_imv_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_tnc_imv_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnc_imv/Makefile.in b/src/libcharon/plugins/tnc_imv/Makefile.in index fb96150f4..cf58f0dc3 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.in +++ b/src/libcharon/plugins/tnc_imv/Makefile.in @@ -74,7 +74,9 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_tnc_imv_la_LIBADD = +@MONOLITHIC_FALSE@libstrongswan_tnc_imv_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la am_libstrongswan_tnc_imv_la_OBJECTS = tnc_imv_plugin.lo tnc_imv.lo \ tnc_imv_manager.lo tnc_imv_bind_function.lo \ tnc_imv_recommendations.lo @@ -195,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -203,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -219,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -267,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -277,12 +286,20 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-imv.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-imv.la +@MONOLITHIC_FALSE@libstrongswan_tnc_imv_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + libstrongswan_tnc_imv_la_SOURCES = \ tnc_imv_plugin.h tnc_imv_plugin.c tnc_imv.h tnc_imv.c \ tnc_imv_manager.h tnc_imv_manager.c tnc_imv_bind_function.c \ diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.c b/src/libcharon/plugins/tnc_imv/tnc_imv.c index fe628ee7e..f0b150743 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Mike McCauley - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-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 @@ -17,8 +18,11 @@ #include <dlfcn.h> +#include <tncif_pa_subtypes.h> + #include <debug.h> #include <library.h> +#include <utils/linked_list.h> #include <threading/mutex.h> typedef struct private_tnc_imv_t private_tnc_imv_t; @@ -54,9 +58,19 @@ struct private_tnc_imv_t { TNC_IMVID id; /** - * List of message types supported by IMC + * List of additional IMV IDs */ - TNC_MessageTypeList supported_types; + linked_list_t *additional_ids; + + /** + * List of message types supported by IMV - Vendor ID part + */ + TNC_VendorIDList supported_vids; + + /** + * List of message types supported by IMV - Subtype part + */ + TNC_MessageSubtypeList supported_subtypes; /** * Number of supported message types @@ -81,6 +95,50 @@ METHOD(imv_t, get_id, TNC_IMVID, return this->id; } +METHOD(imv_t, add_id, void, + private_tnc_imv_t *this, TNC_IMVID id) +{ + TNC_IMVID *new_id; + + new_id = malloc_thing(TNC_IMVID); + *new_id = id; + this->additional_ids->insert_last(this->additional_ids, new_id); +} + +METHOD(imv_t, has_id, bool, + private_tnc_imv_t *this, TNC_IMVID id) +{ + enumerator_t *enumerator; + TNC_IMVID *additional_id; + bool found = FALSE; + + /* check primary IMV ID */ + if (id == this->id) + { + return TRUE; + } + + /* return if there are no additional IMV IDs */ + if (this->additional_ids->get_count(this->additional_ids) == 0) + { + return FALSE; + } + + /* check additional IMV IDs */ + enumerator = this->additional_ids->create_enumerator(this->additional_ids); + while (enumerator->enumerate(enumerator, &additional_id)) + { + if (id == *additional_id) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + METHOD(imv_t, get_name, char*, private_tnc_imv_t *this) { @@ -91,67 +149,150 @@ METHOD(imv_t, set_message_types, void, private_tnc_imv_t *this, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { - char buf[512]; + char buf[BUF_LEN]; char *pos = buf; int len = sizeof(buf); - int written; + int i, written; + size_t size; + TNC_VendorID vid; + TNC_MessageSubtype subtype; + enum_name_t *pa_subtype_names; /* lock the imv_t instance */ this->mutex->lock(this->mutex); - /* Free an existing MessageType list */ - free(this->supported_types); - this->supported_types = NULL; + /* Free existing VendorID and MessageSubtype lists */ + free(this->supported_vids); + this->supported_vids = NULL; + free(this->supported_subtypes); + this->supported_subtypes = NULL; /* Store the new MessageType list */ this->type_count = type_count; if (type_count && supported_types) { - size_t size = type_count * sizeof(TNC_MessageType); - - int i; + size = type_count * sizeof(TNC_VendorID); + this->supported_vids = malloc(size); + size = type_count * sizeof(TNC_MessageSubtype); + this->supported_subtypes = malloc(size); for (i = 0; i < type_count; i++) { - written = snprintf(pos, len, " 0x%08x", supported_types[i]); + vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY; + subtype = supported_types[i] & TNC_SUBTYPE_ANY; + + pa_subtype_names = get_pa_subtype_names(vid); + if (pa_subtype_names) + { + written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x", + pen_names, vid, pa_subtype_names, subtype, + vid, subtype); + } + else + { + written = snprintf(pos, len," '%N' 0x%06x/0x%02x", + pen_names, vid, vid, subtype); + } if (written >= len) { break; } pos += written; len -= written; + + this->supported_vids[i] = vid; + this->supported_subtypes[i] = subtype; } - this->supported_types = malloc(size); - memcpy(this->supported_types, supported_types, size); } *pos = '\0'; - DBG2(DBG_TNC, "IMV %u supports %u message types:%s", - this->id, type_count, buf); + DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s", + this->id, type_count, (type_count == 1) ? "":"s", buf); + + /* unlock the imv_t instance */ + this->mutex->unlock(this->mutex); +} + +METHOD(imv_t, set_message_types_long, void, + private_tnc_imv_t *this, TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count) +{ + char buf[BUF_LEN]; + char *pos = buf; + int len = sizeof(buf); + int i, written; + size_t size; + TNC_VendorID vid; + TNC_MessageSubtype subtype; + enum_name_t *pa_subtype_names; /* lock the imv_t instance */ + this->mutex->lock(this->mutex); + + /* Free existing VendorID and MessageSubtype lists */ + free(this->supported_vids); + this->supported_vids = NULL; + free(this->supported_subtypes); + this->supported_subtypes = NULL; + + /* Store the new MessageType list */ + this->type_count = type_count; + if (type_count && supported_vids && supported_subtypes) + { + size = type_count * sizeof(TNC_VendorID); + this->supported_vids = malloc(size); + memcpy(this->supported_vids, supported_vids, size); + size = type_count * sizeof(TNC_MessageSubtype); + this->supported_subtypes = malloc(size); + memcpy(this->supported_subtypes, supported_subtypes, size); + + for (i = 0; i < type_count; i++) + { + vid = supported_vids[i]; + subtype = supported_subtypes[i]; + + pa_subtype_names = get_pa_subtype_names(vid); + if (pa_subtype_names) + { + written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x", + pen_names, vid, pa_subtype_names, subtype, + vid, subtype); + } + else + { + written = snprintf(pos, len," '%N' 0x%06x/0x%08x", + pen_names, vid, vid, subtype); + } + if (written >= len) + { + break; + } + pos += written; + len -= written; + } + } + *pos = '\0'; + DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s", + this->id, type_count, (type_count == 1) ? "":"s", buf); + + /* unlock the imv_t instance */ this->mutex->unlock(this->mutex); } METHOD(imv_t, type_supported, bool, - private_tnc_imv_t *this, TNC_MessageType message_type) + private_tnc_imv_t *this, TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype) { - TNC_VendorID msg_vid, vid; - TNC_MessageSubtype msg_subtype, subtype; + TNC_VendorID vid; + TNC_MessageSubtype subtype; int i; - msg_vid = (message_type >> 8) & TNC_VENDORID_ANY; - msg_subtype = message_type & TNC_SUBTYPE_ANY; - for (i = 0; i < this->type_count; i++) { - vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY; - subtype = this->supported_types[i] & TNC_SUBTYPE_ANY; - - if (this->supported_types[i] == message_type - || (subtype == TNC_SUBTYPE_ANY - && (msg_vid == vid || vid == TNC_VENDORID_ANY)) - || (vid == TNC_VENDORID_ANY - && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY))) + vid = this->supported_vids[i]; + subtype = this->supported_subtypes[i]; + + if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) || + (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY || + subtype == msg_subtype))) { return TRUE; } @@ -164,7 +305,9 @@ METHOD(imv_t, destroy, void, { dlclose(this->handle); this->mutex->destroy(this->mutex); - free(this->supported_types); + this->additional_ids->destroy_function(this->additional_ids, free); + free(this->supported_vids); + free(this->supported_subtypes); free(this->name); free(this->path); free(this); @@ -181,13 +324,17 @@ imv_t* tnc_imv_create(char *name, char *path) .public = { .set_id = _set_id, .get_id = _get_id, + .add_id = _add_id, + .has_id = _has_id, .get_name = _get_name, .set_message_types = _set_message_types, + .set_message_types_long = _set_message_types_long, .type_supported = _type_supported, .destroy = _destroy, }, .name = name, .path = path, + .additional_ids = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); @@ -222,6 +369,8 @@ imv_t* tnc_imv_create(char *name, char *path) } this->public.receive_message = dlsym(this->handle, "TNC_IMV_ReceiveMessage"); + this->public.receive_message_long = + dlsym(this->handle, "TNC_IMV_ReceiveMessageLong"); this->public.batch_ending = dlsym(this->handle, "TNC_IMV_BatchEnding"); this->public.terminate = diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c index 0ed00b001..dd11c5009 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Mike McCauley - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-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 @@ -13,12 +14,11 @@ * for more details. */ -#include "tnc_imv.h" +#include <tnc/tnc.h> +#include <tnc/imv/imv_manager.h> +#include <tnc/tnccs/tnccs_manager.h> #include <debug.h> -#include <daemon.h> - -#define TNC_IMCID_ANY 0xffff /** * Called by the IMV to inform a TNCS about the set of message types the IMV @@ -28,14 +28,33 @@ TNC_Result TNC_TNCS_ReportMessageTypes(TNC_IMVID imv_id, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->imvs->set_message_types(charon->imvs, imv_id, - supported_types, type_count); + return tnc->imvs->set_message_types(tnc->imvs, imv_id, supported_types, + type_count); +} + +/** + * Called by the IMV to inform a TNCS about the set of message types the IMV + * is able to receive. This function supports long message types. + */ +TNC_Result TNC_TNCS_ReportMessageTypesLong(TNC_IMVID imv_id, + TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, + TNC_UInt32 type_count) +{ + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring ReportMessageTypesLong() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } + return tnc->imvs->set_message_types_long(tnc->imvs, imv_id, supported_vids, + supported_subtypes, type_count); } /** @@ -45,14 +64,14 @@ TNC_Result TNC_TNCS_RequestHandshakeRetry(TNC_IMVID imv_id, TNC_ConnectionID connection_id, TNC_RetryReason reason) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->request_handshake_retry(charon->tnccs, FALSE, imv_id, - connection_id, reason); + return tnc->tnccs->request_handshake_retry(tnc->tnccs, FALSE, imv_id, + connection_id, reason); } /** @@ -64,14 +83,42 @@ TNC_Result TNC_TNCS_SendMessage(TNC_IMVID imv_id, TNC_UInt32 msg_len, TNC_MessageType msg_type) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->send_message(charon->tnccs, TNC_IMCID_ANY, imv_id, - connection_id, msg, msg_len, msg_type); + msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + return tnc->tnccs->send_message(tnc->tnccs, TNC_IMCID_ANY, imv_id, + connection_id, 0, msg, msg_len, msg_vid, msg_subtype); +} + +/** + * Called by the IMV when an IMV-IMC message is to be sent over IF-TNCCS 2.0 + */ +TNC_Result TNC_TNCS_SendMessageLong(TNC_IMVID imv_id, + TNC_ConnectionID connection_id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 imc_id) +{ + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring SendMessageLong() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } + return tnc->tnccs->send_message(tnc->tnccs, imc_id, imv_id, connection_id, + msg_flags, msg, msg_len, msg_vid, msg_subtype); } /** @@ -83,14 +130,14 @@ TNC_Result TNC_TNCS_ProvideRecommendation(TNC_IMVID imv_id, TNC_IMV_Action_Recommendation recommendation, TNC_IMV_Evaluation_Result evaluation) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring ProvideRecommendation() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->provide_recommendation(charon->tnccs, imv_id, - connection_id, recommendation, evaluation); + return tnc->tnccs->provide_recommendation(tnc->tnccs, imv_id, connection_id, + recommendation, evaluation); } /** @@ -104,13 +151,13 @@ TNC_Result TNC_TNCS_GetAttribute(TNC_IMVID imv_id, TNC_BufferReference buffer, TNC_UInt32 *out_value_len) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->get_attribute(charon->tnccs, imv_id, connection_id, + return tnc->tnccs->get_attribute(tnc->tnccs, FALSE, imv_id, connection_id, attribute_id, buffer_len, buffer, out_value_len); } @@ -124,14 +171,28 @@ TNC_Result TNC_TNCS_SetAttribute(TNC_IMVID imv_id, TNC_UInt32 buffer_len, TNC_BufferReference buffer) { - if (!charon->imvs->is_registered(charon->imvs, imv_id)) + if (!tnc->imvs->is_registered(tnc->imvs, imv_id)) { DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMV %u", imv_id); return TNC_RESULT_INVALID_PARAMETER; } - return charon->tnccs->set_attribute(charon->tnccs, imv_id, connection_id, - attribute_id, buffer_len, buffer); + return tnc->tnccs->set_attribute(tnc->tnccs, FALSE, imv_id, connection_id, + attribute_id, buffer_len, buffer); +} + +/** + * Called by the IMV when it wants to reserve an additional IMV ID for itself + */ +TNC_Result TNC_TNCS_ReserveAdditionalIMVID(TNC_IMVID imv_id, TNC_UInt32 *new_id) +{ + if (tnc->imvs->reserve_id(tnc->imvs, imv_id, new_id)) + { + return TNC_RESULT_SUCCESS; + } + DBG1(DBG_TNC, "ignoring ReserveAdditionalIMVID() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; } /** @@ -145,6 +206,10 @@ TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id, { *function_pointer = (void*)TNC_TNCS_ReportMessageTypes; } + else if (streq(function_name, "TNC_TNCS_ReportMessageTypesLong")) + { + *function_pointer = (void*)TNC_TNCS_ReportMessageTypesLong; + } else if (streq(function_name, "TNC_TNCS_RequestHandshakeRetry")) { *function_pointer = (void*)TNC_TNCS_RequestHandshakeRetry; @@ -153,6 +218,10 @@ TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id, { *function_pointer = (void*)TNC_TNCS_SendMessage; } + else if (streq(function_name, "TNC_TNCS_SendMessageLong")) + { + *function_pointer = (void*)TNC_TNCS_SendMessageLong; + } else if (streq(function_name, "TNC_TNCS_ProvideRecommendation")) { *function_pointer = (void*)TNC_TNCS_ProvideRecommendation; @@ -165,6 +234,10 @@ TNC_Result TNC_TNCS_BindFunction(TNC_IMVID id, { *function_pointer = (void*)TNC_TNCS_SetAttribute; } + else if (streq(function_name, "TNC_TNCS_ReserveAdditionalIMVID")) + { + *function_pointer = (void*)TNC_TNCS_ReserveAdditionalIMVID; + } else { return TNC_RESULT_INVALID_PARAMETER; diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c index 579ab06ff..b1da73156 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Mike McCauley - * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * Copyright (C) 2010-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 @@ -14,13 +15,22 @@ */ #include "tnc_imv_manager.h" +#include "tnc_imv.h" #include "tnc_imv_recommendations.h" -#include <tnc/imv/imv_manager.h> -#include <tnc/tncifimv.h> +#include <tncifimv.h> +#include <tncif_names.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> -#include <debug.h> #include <daemon.h> +#include <utils/lexparser.h> +#include <debug.h> #include <threading/mutex.h> typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t; @@ -101,6 +111,33 @@ METHOD(imv_manager_t, remove_, imv_t*, return removed_imv; } +METHOD(imv_manager_t, load, bool, + private_tnc_imv_manager_t *this, char *name, char *path) +{ + imv_t *imv; + + imv = tnc_imv_create(name, path); + if (!imv) + { + free(name); + free(path); + return FALSE; + } + if (!add(this, imv)) + { + if (imv->terminate && + imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully", + imv->get_name(imv)); + } + imv->destroy(imv); + return FALSE; + } + DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), name, path); + return TRUE; +} + METHOD(imv_manager_t, is_registered, bool, private_tnc_imv_manager_t *this, TNC_IMVID id) { @@ -111,9 +148,34 @@ METHOD(imv_manager_t, is_registered, bool, enumerator = this->imvs->create_enumerator(this->imvs); while (enumerator->enumerate(enumerator, &imv)) { - if (id == imv->get_id(imv)) + if (imv->has_id(imv, id)) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + +METHOD(imv_manager_t, reserve_id, bool, + private_tnc_imv_manager_t *this, TNC_IMVID id, TNC_UInt32 *new_id) +{ + enumerator_t *enumerator; + imv_t *imv; + bool found = FALSE; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (imv->get_id(imv)) { found = TRUE; + *new_id = this->next_imv_id++; + imv->add_id(imv, *new_id); + DBG2(DBG_TNC, "additional ID %u reserved for IMV with primary ID %u", + *new_id, id); break; } } @@ -231,6 +293,31 @@ METHOD(imv_manager_t, set_message_types, TNC_Result, return result; } +METHOD(imv_manager_t, set_message_types_long, TNC_Result, + private_tnc_imv_manager_t *this, TNC_IMVID id, + TNC_VendorIDList supported_vids, + TNC_MessageSubtypeList supported_subtypes, + TNC_UInt32 type_count) +{ + enumerator_t *enumerator; + imv_t *imv; + TNC_Result result = TNC_RESULT_FATAL; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (id == imv->get_id(imv)) + { + imv->set_message_types_long(imv, supported_vids, supported_subtypes, + type_count); + result = TNC_RESULT_SUCCESS; + break; + } + } + enumerator->destroy(enumerator); + return result; +} + METHOD(imv_manager_t, solicit_recommendation, void, private_tnc_imv_manager_t *this, TNC_ConnectionID id) { @@ -247,28 +334,52 @@ METHOD(imv_manager_t, solicit_recommendation, void, METHOD(imv_manager_t, receive_message, void, private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id, - TNC_BufferReference message, - TNC_UInt32 message_len, - TNC_MessageType message_type) + bool excl, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype, + TNC_UInt32 src_imc_id, + TNC_UInt32 dst_imv_id) { bool type_supported = FALSE; + TNC_MessageType msg_type; + TNC_UInt32 msg_flags; enumerator_t *enumerator; imv_t *imv; + msg_type = (msg_vid << 8) | msg_subtype; + enumerator = this->imvs->create_enumerator(this->imvs); while (enumerator->enumerate(enumerator, &imv)) { - if (imv->receive_message && imv->type_supported(imv, message_type)) + if (imv->type_supported(imv, msg_vid, msg_subtype) && + (!excl || (excl && imv->has_id(imv, dst_imv_id)) )) { - type_supported = TRUE; - imv->receive_message(imv->get_id(imv), connection_id, - message, message_len, message_type); + if (imv->receive_message_long && src_imc_id) + { + type_supported = TRUE; + msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0; + imv->receive_message_long(imv->get_id(imv), connection_id, + msg_flags, msg, msg_len, msg_vid, msg_subtype, + src_imc_id, dst_imv_id); + + } + else if (imv->receive_message && msg_vid <= TNC_VENDORID_ANY && + msg_subtype <= TNC_SUBTYPE_ANY) + { + type_supported = TRUE; + msg_type = (msg_vid << 8) | msg_subtype; + imv->receive_message(imv->get_id(imv), connection_id, + msg, msg_len, msg_type); + } } } enumerator->destroy(enumerator); if (!type_supported) { - DBG2(DBG_TNC, "message type 0x%08x not supported by any IMV", message_type); + DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMV", + msg_vid, msg_subtype); } } @@ -289,6 +400,7 @@ METHOD(imv_manager_t, batch_ending, void, enumerator->destroy(enumerator); } + METHOD(imv_manager_t, destroy, void, private_tnc_imv_manager_t *this) { @@ -320,12 +432,15 @@ imv_manager_t* tnc_imv_manager_create(void) .public = { .add = _add, .remove = _remove_, /* avoid name conflict with stdio.h */ + .load = _load, .is_registered = _is_registered, + .reserve_id = _reserve_id, .get_recommendation_policy = _get_recommendation_policy, .create_recommendations = _create_recommendations, .enforce_recommendation = _enforce_recommendation, .notify_connection_change = _notify_connection_change, .set_message_types = _set_message_types, + .set_message_types_long = _set_message_types_long, .solicit_recommendation = _solicit_recommendation, .receive_message = _receive_message, .batch_ending = _batch_ending, @@ -334,6 +449,7 @@ imv_manager_t* tnc_imv_manager_create(void) .imvs = linked_list_create(), .next_imv_id = 1, ); + policy = enum_from_name(recommendation_policy_names, lib->settings->get_str(lib->settings, "charon.plugins.tnc-imv.recommendation_policy", "default")); diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c index 45cf95c1b..c16f6b9e1 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2011 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,137 +15,24 @@ #include "tnc_imv_plugin.h" #include "tnc_imv_manager.h" -#include "tnc_imv.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> +#include <tnc/tnc.h> -#include <daemon.h> -#include <utils/lexparser.h> + +typedef struct private_tnc_imv_plugin_t private_tnc_imv_plugin_t; /** - * load IMVs from a configuration file + * Private data of a tnc_imv_plugin_t object. */ -static bool load_imvs(char *filename) -{ - int fd, line_nr = 0; - chunk_t src, line; - struct stat sb; - void *addr; - - DBG1(DBG_TNC, "loading IMVs from '%s'", filename); - fd = open(filename, O_RDONLY); - if (fd == -1) - { - DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, - strerror(errno)); - return FALSE; - } - if (fstat(fd, &sb) == -1) - { - DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, - strerror(errno)); - close(fd); - return FALSE; - } - addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (addr == MAP_FAILED) - { - DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); - close(fd); - return FALSE; - } - src = chunk_create(addr, sb.st_size); - - while (fetchline(&src, &line)) - { - char *name, *path; - chunk_t token; - imv_t *imv; - - line_nr++; - - /* skip comments or empty lines */ - if (*line.ptr == '#' || !eat_whitespace(&line)) - { - continue; - } - - /* determine keyword */ - if (!extract_token(&token, ' ', &line)) - { - DBG1(DBG_TNC, "line %d: keyword must be followed by a space", - line_nr); - return FALSE; - } - - /* only interested in IMVs */ - if (!match("IMV", &token)) - { - continue; - } - - /* advance to the IMV name and extract it */ - if (!extract_token(&token, '"', &line) || - !extract_token(&token, '"', &line)) - { - DBG1(DBG_TNC, "line %d: IMV name must be set in double quotes", - line_nr); - return FALSE; - } +struct private_tnc_imv_plugin_t { - /* copy the IMV name */ - name = malloc(token.len + 1); - memcpy(name, token.ptr, token.len); - name[token.len] = '\0'; + /** + * Public interface. + */ + tnc_imv_plugin_t public; - /* advance to the IMV path and extract it */ - if (!eat_whitespace(&line)) - { - DBG1(DBG_TNC, "line %d: IMV path is missing", line_nr); - free(name); - return FALSE; - } - if (!extract_token(&token, ' ', &line)) - { - token = line; - } +}; - /* copy the IMV path */ - path = malloc(token.len + 1); - memcpy(path, token.ptr, token.len); - path[token.len] = '\0'; - - /* load and register IMV instance */ - imv = tnc_imv_create(name, path); - if (!imv) - { - free(name); - free(path); - return FALSE; - } - if (!charon->imvs->add(charon->imvs, imv)) - { - if (imv->terminate && - imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS) - { - DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully", - imv->get_name(imv)); - } - imv->destroy(imv); - return FALSE; - } - DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), - name, path); - } - munmap(addr, sb.st_size); - close(fd); - return TRUE; -} METHOD(plugin_t, get_name, char*, tnc_imv_plugin_t *this) @@ -153,10 +40,21 @@ METHOD(plugin_t, get_name, char*, return "tnc-imv"; } +METHOD(plugin_t, get_features, int, + private_tnc_imv_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnc_manager_register, tnc_imv_manager_create), + PLUGIN_PROVIDE(CUSTOM, "imv-manager"), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, - tnc_imv_plugin_t *this) + private_tnc_imv_plugin_t *this) { - charon->imvs->destroy(charon->imvs); free(this); } @@ -165,31 +63,18 @@ METHOD(plugin_t, destroy, void, */ plugin_t *tnc_imv_plugin_create() { - char *tnc_config; - tnc_imv_plugin_t *this; + private_tnc_imv_plugin_t *this; INIT(this, - .plugin = { - .get_name = _get_name, - .reload = (void*)return_false, - .destroy = _destroy, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, }, ); - tnc_config = lib->settings->get_str(lib->settings, - "charon.plugins.tnc-imv.tnc_config", "/etc/tnc_config"); - - /* Create IMV manager */ - charon->imvs = tnc_imv_manager_create(); - - /* Load IMVs and abort if not all instances initalize successfully */ - if (!load_imvs(tnc_config)) - { - charon->imvs->destroy(charon->imvs); - charon->imvs = NULL; - free(this); - return NULL; - } - return &this->plugin; + return &this->public.plugin; } diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c index 5cc6b0ced..7843293a1 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_recommendations.c @@ -12,12 +12,17 @@ * for more details. */ -#include <debug.h> -#include <daemon.h> -#include <tnc/tncifimv.h> +#include <tncifimv.h> +#include <tncif_names.h> + +#include <tnc/tnc.h> #include <tnc/imv/imv.h> +#include <tnc/imv/imv_manager.h> #include <tnc/imv/imv_recommendations.h> +#include <debug.h> +#include <utils/linked_list.h> + typedef struct private_tnc_imv_recommendations_t private_tnc_imv_recommendations_t; typedef struct recommendation_entry_t recommendation_entry_t; @@ -126,7 +131,7 @@ METHOD(recommendations_t, have_recommendation, bool, DBG1(DBG_TNC, "there are no IMVs to make a recommendation"); return TRUE; } - policy = charon->imvs->get_recommendation_policy(charon->imvs); + policy = tnc->imvs->get_recommendation_policy(tnc->imvs); enumerator = this->recs->create_enumerator(this->recs); while (enumerator->enumerate(enumerator, &entry)) @@ -357,6 +362,21 @@ METHOD(recommendations_t, create_reason_enumerator, enumerator_t*, (void*)reason_filter, NULL, NULL); } +METHOD(recommendations_t, clear_reasons, void, + private_tnc_imv_recommendations_t *this) +{ + enumerator_t *enumerator; + recommendation_entry_t *entry; + + enumerator = this->recs->create_enumerator(this->recs); + while (enumerator->enumerate(enumerator, &entry)) + { + chunk_clear(&entry->reason); + chunk_clear(&entry->reason_language); + } + enumerator->destroy(enumerator); +} + METHOD(recommendations_t, destroy, void, private_tnc_imv_recommendations_t *this) { @@ -392,6 +412,7 @@ recommendations_t* tnc_imv_recommendations_create(linked_list_t *imv_list) .set_reason_string = _set_reason_string, .set_reason_language = _set_reason_language, .create_reason_enumerator = _create_reason_enumerator, + .clear_reasons = _clear_reasons, .destroy = _destroy, }, .recs = linked_list_create(), diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am new file mode 100644 index 000000000..2d4c4d55a --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/Makefile.am @@ -0,0 +1,24 @@ + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libradius + +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/libradius/libradius.la \ + $(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 tnc_pdp_connections.h tnc_pdp_connections.c + +libstrongswan_tnc_pdp_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in new file mode 100644 index 000000000..70d3d6249 --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/Makefile.in @@ -0,0 +1,627 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/tnc_pdp +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +@MONOLITHIC_FALSE@libstrongswan_tnc_pdp_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libradius/libradius.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la +am_libstrongswan_tnc_pdp_la_OBJECTS = tnc_pdp_plugin.lo tnc_pdp.lo \ + tnc_pdp_connections.lo +libstrongswan_tnc_pdp_la_OBJECTS = \ + $(am_libstrongswan_tnc_pdp_la_OBJECTS) +libstrongswan_tnc_pdp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_tnc_pdp_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_tnc_pdp_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_tnc_pdp_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_tnc_pdp_la_SOURCES) +DIST_SOURCES = $(libstrongswan_tnc_pdp_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libradius + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la +@MONOLITHIC_FALSE@libstrongswan_tnc_pdp_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libradius/libradius.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + +libstrongswan_tnc_pdp_la_SOURCES = \ + tnc_pdp_plugin.h tnc_pdp_plugin.c \ + tnc_pdp.h tnc_pdp.c tnc_pdp_connections.h tnc_pdp_connections.c + +libstrongswan_tnc_pdp_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_pdp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_pdp/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-tnc-pdp.la: $(libstrongswan_tnc_pdp_la_OBJECTS) $(libstrongswan_tnc_pdp_la_DEPENDENCIES) + $(libstrongswan_tnc_pdp_la_LINK) $(am_libstrongswan_tnc_pdp_la_rpath) $(libstrongswan_tnc_pdp_la_OBJECTS) $(libstrongswan_tnc_pdp_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_pdp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_pdp_connections.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_pdp_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c new file mode 100644 index 000000000..0625baa90 --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c @@ -0,0 +1,648 @@ +/* + * Copyright (C) 2012 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 "tnc_pdp_connections.h" + +#include <errno.h> +#include <unistd.h> + +#include <radius_message.h> +#include <radius_mppe.h> + +#include <daemon.h> +#include <debug.h> +#include <pen/pen.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> +#include <sa/authenticators/eap/eap_method.h> + +typedef struct private_tnc_pdp_t private_tnc_pdp_t; + +/** + * Maximum size of a RADIUS IP packet + */ +#define MAX_PACKET 4096 + +/** + * private data of tnc_pdp_t + */ +struct private_tnc_pdp_t { + + /** + * implements tnc_pdp_t interface + */ + tnc_pdp_t public; + + /** + * ID of the server + */ + identification_t *server; + + /** + * EAP method type to be used + */ + eap_type_t type; + + /** + * IPv4 RADIUS socket + */ + int ipv4; + + /** + * IPv6 RADIUS socket + */ + int ipv6; + + /** + * Callback job dispatching commands + */ + callback_job_t *job; + + /** + * RADIUS shared secret + */ + chunk_t secret; + + /** + * MD5 hasher + */ + hasher_t *hasher; + + /** + * HMAC MD5 signer, with secret set + */ + signer_t *signer; + + /** + * Random number generator for MS-MPPE salt values + */ + rng_t *rng; + + /** + * List of registered TNC-PDP connections + */ + tnc_pdp_connections_t *connections; +}; + + +/** + * Open IPv4 or IPv6 UDP RADIUS socket + */ +static int open_socket(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_CFG, "opening RADIUS socket failed: %s", strerror(errno)); + return 0; + } + if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0) + { + DBG1(DBG_CFG, "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_CFG, "unable to bind RADIUS socket: %s", strerror(errno)); + close(skt); + return 0; + } + + return skt; +} + +/** + * Send a RADIUS message to client + */ +static void send_message(private_tnc_pdp_t *this, radius_message_t *message, + host_t *client) +{ + int fd; + chunk_t data; + + fd = (client->get_family(client) == AF_INET) ? this->ipv4 : this->ipv6; + data = message->get_encoding(message); + + DBG2(DBG_CFG, "sending RADIUS packet to %#H", client); + DBG3(DBG_CFG, "%B", &data); + + if (sendto(fd, data.ptr, data.len, 0, client->get_sockaddr(client), + *client->get_sockaddr_len(client)) != data.len) + { + DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); + } +} + +/** + * Encrypt a MS-MPPE-Send/Recv-Key + */ +static chunk_t encrypt_mppe_key(private_tnc_pdp_t *this, u_int8_t type, + chunk_t key, u_int16_t *salt, + radius_message_t *request) +{ + chunk_t a, r, seed, data; + u_char b[HASH_SIZE_MD5], *c; + mppe_key_t *mppe_key; + + /** + * From RFC2548 (encryption): + * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) + * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) + * . . . + * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) + */ + + data = chunk_alloc(sizeof(mppe_key_t) + + HASH_SIZE_MD5 * (1 + key.len / HASH_SIZE_MD5)); + memset(data.ptr, 0x00, data.len); + + mppe_key = (mppe_key_t*)data.ptr; + mppe_key->id = htonl(PEN_MICROSOFT); + mppe_key->type = type; + mppe_key->length = data.len - sizeof(mppe_key->id); + mppe_key->key[0] = key.len; + + memcpy(&mppe_key->key[1], key.ptr, key.len); + + /** + * generate a 16 bit unique random salt value for the MPPE stream cipher + * the MSB of the salt MUST be set to 1 + */ + a = chunk_create((u_char*)&(mppe_key->salt), sizeof(mppe_key->salt)); + do + { + this->rng->get_bytes(this->rng, a.len, a.ptr); + *a.ptr |= 0x80; + } + while (mppe_key->salt == *salt); + + /* update the salt value */ + *salt = mppe_key->salt; + + r = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); + seed = chunk_cata("cc", r, a); + + c = mppe_key->key; + while (c < data.ptr + data.len) + { + /* b(i) = MD5(S + c(i-1)) */ + this->hasher->get_hash(this->hasher, this->secret, NULL); + this->hasher->get_hash(this->hasher, seed, b); + + /* c(i) = b(i) xor p(1) */ + memxor(c, b, HASH_SIZE_MD5); + + /* prepare next round */ + seed = chunk_create(c, HASH_SIZE_MD5); + c += HASH_SIZE_MD5; + } + + return data; +} + +/** + * Send a RADIUS response for a request + */ +static void send_response(private_tnc_pdp_t *this, radius_message_t *request, + radius_message_code_t code, eap_payload_t *eap, + identification_t *group, chunk_t msk, host_t *client) +{ + radius_message_t *response; + chunk_t data, recv, send; + u_int32_t tunnel_type; + u_int16_t salt = 0; + + response = radius_message_create(code); + if (eap) + { + data = eap->get_data(eap); + DBG3(DBG_CFG, "%N payload %B", eap_type_names, this->type, &data); + + /* fragment data suitable for RADIUS */ + while (data.len > MAX_RADIUS_ATTRIBUTE_SIZE) + { + response->add(response, RAT_EAP_MESSAGE, + chunk_create(data.ptr, MAX_RADIUS_ATTRIBUTE_SIZE)); + data = chunk_skip(data, MAX_RADIUS_ATTRIBUTE_SIZE); + } + response->add(response, RAT_EAP_MESSAGE, data); + } + if (group) + { + tunnel_type = RADIUS_TUNNEL_TYPE_ESP; + htoun32(data.ptr, tunnel_type); + data.len = sizeof(tunnel_type); + response->add(response, RAT_TUNNEL_TYPE, data); + response->add(response, RAT_FILTER_ID, group->get_encoding(group)); + } + if (msk.len) + { + recv = chunk_create(msk.ptr, msk.len / 2); + data = encrypt_mppe_key(this, MS_MPPE_RECV_KEY, recv, &salt, request); + response->add(response, RAT_VENDOR_SPECIFIC, data); + chunk_free(&data); + + send = chunk_create(msk.ptr + recv.len, msk.len - recv.len); + data = encrypt_mppe_key(this, MS_MPPE_SEND_KEY, send, &salt, request); + response->add(response, RAT_VENDOR_SPECIFIC, data); + chunk_free(&data); + } + response->set_identifier(response, request->get_identifier(request)); + response->sign(response, request->get_authenticator(request), + this->secret, this->hasher, this->signer, NULL, TRUE); + + DBG1(DBG_CFG, "sending RADIUS %N to client '%H'", radius_message_code_names, + code, client); + send_message(this, response, client); + response->destroy(response); +} + +/** + * Process EAP message + */ +static void process_eap(private_tnc_pdp_t *this, radius_message_t *request, + host_t *source) +{ + enumerator_t *enumerator; + eap_payload_t *in, *out = NULL; + eap_method_t *method; + eap_type_t eap_type; + u_int32_t eap_vendor; + chunk_t data, message = chunk_empty, msk = chunk_empty; + chunk_t user_name = chunk_empty, nas_id = chunk_empty; + identification_t *group = NULL; + radius_message_code_t code = RMC_ACCESS_CHALLENGE; + int type; + + enumerator = request->create_enumerator(request); + while (enumerator->enumerate(enumerator, &type, &data)) + { + switch (type) + { + case RAT_USER_NAME: + user_name = data; + break; + case RAT_NAS_IDENTIFIER: + nas_id = data; + break; + case RAT_EAP_MESSAGE: + if (data.len) + { + message = chunk_cat("mc", message, data); + } + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (message.len) + { + in = eap_payload_create_data(message); + + /* apply EAP method selected by RADIUS server */ + eap_type = in->get_type(in, &eap_vendor); + + DBG3(DBG_CFG, "%N payload %B", eap_type_names, eap_type, &message); + + if (eap_type == EAP_IDENTITY) + { + identification_t *peer; + chunk_t eap_identity; + + if (message.len < 5) + { + goto end; + } + eap_identity = chunk_create(message.ptr + 5, message.len - 5); + peer = identification_create_from_data(eap_identity); + method = charon->eap->create_instance(charon->eap, this->type, + 0, EAP_SERVER, this->server, peer); + if (!method) + { + peer->destroy(peer); + goto end; + } + this->connections->add(this->connections, nas_id, user_name, peer, + method); + method->initiate(method, &out); + } + else + { + ike_sa_t *ike_sa; + auth_cfg_t *auth; + auth_rule_t type; + identification_t *data; + enumerator_t *e; + + method = this->connections->get_state(this->connections, nas_id, + user_name, &ike_sa); + if (!method) + { + goto end; + } + charon->bus->set_sa(charon->bus, ike_sa); + + switch (method->process(method, in, &out)) + { + case NEED_MORE: + code = RMC_ACCESS_CHALLENGE; + break; + case SUCCESS: + code = RMC_ACCESS_ACCEPT; + method->get_msk(method, &msk); + auth = ike_sa->get_auth_cfg(ike_sa, FALSE); + e = auth->create_enumerator(auth); + while (e->enumerate(e, &type, &data)) + { + /* look for group memberships */ + if (type == AUTH_RULE_GROUP) + { + group = data; + } + } + e->destroy(e); + + DESTROY_IF(out); + out = eap_payload_create_code(EAP_SUCCESS, + in->get_identifier(in)); + break; + case FAILED: + default: + code = RMC_ACCESS_REJECT; + DESTROY_IF(out); + out = eap_payload_create_code(EAP_FAILURE, + in->get_identifier(in)); + } + charon->bus->set_sa(charon->bus, NULL); + } + + send_response(this, request, code, out, group, msk, source); + out->destroy(out); + + if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT) + { + this->connections->remove(this->connections, nas_id, user_name); + } + +end: + free(message.ptr); + in->destroy(in); + } +} + +/** + * Process packets received on the RADIUS socket + */ +static job_requeue_t receive(private_tnc_pdp_t *this) +{ + while (TRUE) + { + radius_message_t *request; + 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_CFG, "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_CFG, "error reading RADIUS socket: %s", strerror(errno)); + continue; + } + if (msg.msg_flags & MSG_TRUNC) + { + DBG1(DBG_CFG, "receive buffer too small, RADIUS packet discarded"); + continue; + } + source = host_create_from_sockaddr((sockaddr_t*)&src); + DBG2(DBG_CFG, "received RADIUS packet from %#H", source); + DBG3(DBG_CFG, "%b", buffer, bytes_read); + request = radius_message_parse(chunk_create(buffer, bytes_read)); + if (request) + { + DBG1(DBG_CFG, "received RADIUS %N from client '%H'", + radius_message_code_names, request->get_code(request), source); + + if (request->verify(request, NULL, this->secret, this->hasher, + this->signer)) + { + process_eap(this, request, source); + } + request->destroy(request); + + } + else + { + DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); + } + source->destroy(source); + } + return JOB_REQUEUE_FAIR; +} + +METHOD(tnc_pdp_t, destroy, void, + private_tnc_pdp_t *this) +{ + if (this->job) + { + this->job->cancel(this->job); + } + if (this->ipv4) + { + close(this->ipv4); + } + if (this->ipv6) + { + close(this->ipv6); + } + DESTROY_IF(this->server); + DESTROY_IF(this->signer); + DESTROY_IF(this->hasher); + DESTROY_IF(this->rng); + DESTROY_IF(this->connections); + free(this); +} + +/* + * see header file + */ +tnc_pdp_t *tnc_pdp_create(u_int16_t port) +{ + private_tnc_pdp_t *this; + char *secret, *server, *eap_type_str; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .ipv4 = open_socket(AF_INET, port), + .ipv6 = open_socket(AF_INET6, port), + .hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5), + .signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128), + .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK), + .connections = tnc_pdp_connections_create(), + ); + + if (!this->hasher || !this->signer || !this->rng) + { + DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required"); + destroy(this); + return NULL; + } + if (!this->ipv4 && !this->ipv6) + { + DBG1(DBG_NET, "could 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"); + } + + server = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-pdp.server", NULL); + if (!server) + { + DBG1(DBG_CFG, "missing PDP server name, PDP disabled"); + destroy(this); + return NULL; + } + this->server = identification_create_from_string(server); + + secret = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-pdp.secret", NULL); + if (!secret) + { + DBG1(DBG_CFG, "missing RADIUS secret, PDP disabled"); + destroy(this); + return NULL; + } + this->secret = chunk_create(secret, strlen(secret)); + this->signer->set_key(this->signer, this->secret); + + eap_type_str = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-pdp.method", "ttls"); + this->type = eap_type_from_string(eap_type_str); + if (this->type == 0) + { + DBG1(DBG_CFG, "unrecognized eap method \"%s\"", eap_type_str); + destroy(this); + return NULL; + } + DBG1(DBG_IKE, "eap method %N selected", eap_type_names, this->type); + + 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; +} + diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h new file mode 100644 index 000000000..06291220f --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.h @@ -0,0 +1,46 @@ +/* + * 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_t 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_ @}*/ diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c new file mode 100644 index 000000000..175a57aba --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2012 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_connections.h" + +#include <utils/linked_list.h> +#include <debug.h> + +typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t; +typedef struct entry_t entry_t; + +/** + * Private data of tnc_pdp_connections_t + */ +struct private_tnc_pdp_connections_t { + + /** + * Implements tnc_pdp_connections_t interface + */ + tnc_pdp_connections_t public; + + /** + * List of TNC PEP RADIUS Connections + */ + linked_list_t *list; +}; + +/** + * Data entry for a TNC PEP RADIUS connection + */ +struct entry_t { + + /** + * NAS identifier of PEP + */ + chunk_t nas_id; + + /** + * User name of TNC Client + */ + chunk_t user_name; + + /** + * EAP method state + */ + eap_method_t *method; + + /** + * IKE SA used for bus communication + */ + ike_sa_t *ike_sa; +}; + +/** + * Free the memory allocated to a data entry + */ +static void free_entry(entry_t *this) +{ + this->method->destroy(this->method); + this->ike_sa->destroy(this->ike_sa); + free(this->nas_id.ptr); + free(this->user_name.ptr); + free(this); +} + +/** + * Find a matching data entry + */ +static bool equals_entry( entry_t *this, chunk_t nas_id, chunk_t user_name) +{ + bool no_nas_id = !this->nas_id.ptr && !nas_id.ptr; + + return (chunk_equals(this->nas_id, nas_id) || no_nas_id) && + chunk_equals(this->user_name, user_name); +} + +/** + * Find a matching data entry + */ +static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op) +{ + if (nas_id.len) + { + DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s' NAS '%.*s'", + not ? "could not find" : op, user_name.len, user_name.ptr, + nas_id.len, nas_id.ptr); + } + else + { + DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'", + not ? "could not find" : op, user_name.len, user_name.ptr); + } +} + +METHOD(tnc_pdp_connections_t, add, void, + private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name, + identification_t *peer, eap_method_t *method) +{ + enumerator_t *enumerator; + entry_t *entry; + ike_sa_id_t *ike_sa_id; + ike_sa_t *ike_sa; + bool found = FALSE; + + ike_sa_id = ike_sa_id_create(0, 0, FALSE); + ike_sa = ike_sa_create(ike_sa_id); + ike_sa_id->destroy(ike_sa_id); + ike_sa->set_other_id(ike_sa, peer); + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (equals_entry(entry, nas_id, user_name)) + { + found = TRUE; + entry->method->destroy(entry->method); + entry->ike_sa->destroy(entry->ike_sa); + DBG1(DBG_CFG, "removed stale RADIUS connection"); + entry->method = method; + entry->ike_sa = ike_sa; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + entry = malloc_thing(entry_t); + entry->nas_id = chunk_clone(nas_id); + entry->user_name = chunk_clone(user_name); + entry->method = method; + entry->ike_sa = ike_sa; + this->list->insert_last(this->list, entry); + } + dbg_nas_user(nas_id, user_name, FALSE, "created"); +} + +METHOD(tnc_pdp_connections_t, remove_, void, + private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name) +{ + enumerator_t *enumerator; + entry_t *entry; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (equals_entry(entry, nas_id, user_name)) + { + free_entry(entry); + this->list->remove_at(this->list, enumerator); + dbg_nas_user(nas_id, user_name, FALSE, "removed"); + break; + } + } + enumerator->destroy(enumerator); +} + +METHOD(tnc_pdp_connections_t, get_state, eap_method_t*, + private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name, + ike_sa_t **ike_sa) +{ + enumerator_t *enumerator; + entry_t *entry; + eap_method_t *found = NULL; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (equals_entry(entry, nas_id, user_name)) + { + found = entry->method; + *ike_sa = entry->ike_sa; + break; + } + } + enumerator->destroy(enumerator); + + dbg_nas_user(nas_id, user_name, !found, "found"); + return found; +} + +METHOD(tnc_pdp_connections_t, destroy, void, + private_tnc_pdp_connections_t *this) +{ + this->list->destroy_function(this->list, (void*)free_entry); + free(this); +} + +/* + * see header file + */ +tnc_pdp_connections_t *tnc_pdp_connections_create(void) +{ + private_tnc_pdp_connections_t *this; + + INIT(this, + .public = { + .add = _add, + .remove = _remove_, + .get_state = _get_state, + .destroy = _destroy, + }, + .list = linked_list_create(), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h new file mode 100644 index 000000000..b9f5d097b --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 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_connections tnc_pdp_connections + * @{ @ingroup tnc_pdp + */ + +#ifndef TNC_PDP_CONNECTIONS_H_ +#define TNC_PDP_CONNECTIONS_H_ + +typedef struct tnc_pdp_connections_t tnc_pdp_connections_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/authenticators/eap/eap_method.h> + +/** + * Public interface of a tnc_pdp_connections object + */ +struct tnc_pdp_connections_t { + + /** + * Register a new TNC PEP RADIUS Connection + * + * @param nas_id NAS identifier of Policy Enforcement Point + * @param user_name User name of TNC Client + * @param peer Peer identity + * @param method EAP method state for this TNC PEP Connection + */ + void (*add)(tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name, + identification_t *peer, eap_method_t *method); + + /** + * Remove a TNC PEP RADIUS Connection + * + * @param nas_id NAS identifier of Policy Enforcement Point + * @param user_name User name of TNC Client + */ + void (*remove)(tnc_pdp_connections_t *this, chunk_t nas_id, + chunk_t user_name); + + /** + * Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection + * + * @param nas_id NAS identifier of Policy Enforcement Point + * @param user_name User name of TNC Client + * @param ike_sa IKE_SA used for bus communication only + * @return EAP method for this connection or NULL if not found + */ + eap_method_t* (*get_state)(tnc_pdp_connections_t *this, chunk_t nas_id, + chunk_t user_name, ike_sa_t **ike_sa); + + /** + * Destroys a tnc_pdp_connections_t object. + */ + void (*destroy)(tnc_pdp_connections_t *this); +}; + +/** + * Create a tnc_pdp_connections_t instance + */ +tnc_pdp_connections_t* tnc_pdp_connections_create(void); + +#endif /** TNC_PDP_CONNECTIONS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c new file mode 100644 index 000000000..9abe02aec --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.c @@ -0,0 +1,91 @@ +/* + * 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.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; +} + diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.h new file mode 100644 index 000000000..9b8b9ff0e --- /dev/null +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_plugin.h @@ -0,0 +1,42 @@ +/* + * 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_ @}*/ diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.am b/src/libcharon/plugins/tnc_tnccs/Makefile.am new file mode 100644 index 000000000..c7fc02f7c --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/Makefile.am @@ -0,0 +1,22 @@ + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la +else +plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la +libstrongswan_tnc_tnccs_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la +endif + +libstrongswan_tnc_tnccs_la_SOURCES = \ + tnc_tnccs_plugin.h tnc_tnccs_plugin.c \ + tnc_tnccs_manager.h tnc_tnccs_manager.c + +libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.in b/src/libcharon/plugins/tnc_tnccs/Makefile.in new file mode 100644 index 000000000..c12a837d1 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/Makefile.in @@ -0,0 +1,624 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/tnc_tnccs +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +@MONOLITHIC_FALSE@libstrongswan_tnc_tnccs_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la +am_libstrongswan_tnc_tnccs_la_OBJECTS = tnc_tnccs_plugin.lo \ + tnc_tnccs_manager.lo +libstrongswan_tnc_tnccs_la_OBJECTS = \ + $(am_libstrongswan_tnc_tnccs_la_OBJECTS) +libstrongswan_tnc_tnccs_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_tnc_tnccs_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_tnc_tnccs_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_tnc_tnccs_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_tnc_tnccs_la_SOURCES) +DIST_SOURCES = $(libstrongswan_tnc_tnccs_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la +@MONOLITHIC_FALSE@libstrongswan_tnc_tnccs_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + +libstrongswan_tnc_tnccs_la_SOURCES = \ + tnc_tnccs_plugin.h tnc_tnccs_plugin.c \ + tnc_tnccs_manager.h tnc_tnccs_manager.c + +libstrongswan_tnc_tnccs_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_tnccs/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/tnc_tnccs/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-tnc-tnccs.la: $(libstrongswan_tnc_tnccs_la_OBJECTS) $(libstrongswan_tnc_tnccs_la_DEPENDENCIES) + $(libstrongswan_tnc_tnccs_la_LINK) $(am_libstrongswan_tnc_tnccs_la_rpath) $(libstrongswan_tnc_tnccs_la_OBJECTS) $(libstrongswan_tnc_tnccs_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_tnccs_manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnc_tnccs_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c new file mode 100644 index 000000000..64ed160d9 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c @@ -0,0 +1,712 @@ +/* + * 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_tnccs_manager.h" + +#include <tnc/tnc.h> +#include <tnc/imv/imv_manager.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/imv/imv_manager.h> + +#include <debug.h> +#include <utils/linked_list.h> +#include <threading/rwlock.h> + +typedef struct private_tnc_tnccs_manager_t private_tnc_tnccs_manager_t; +typedef struct tnccs_entry_t tnccs_entry_t; +typedef struct tnccs_connection_entry_t tnccs_connection_entry_t; + +/** + * TNCCS constructor entry + */ +struct tnccs_entry_t { + + /** + * TNCCS protocol type + */ + tnccs_type_t type; + + /** + * constructor function to create instance + */ + tnccs_constructor_t constructor; +}; + +/** + * TNCCS connection entry + */ +struct tnccs_connection_entry_t { + + /** + * TNCCS connection ID + */ + TNC_ConnectionID id; + + /** + * TNCCS protocol type + */ + tnccs_type_t type; + + /** + * TNCCS instance + */ + tnccs_t *tnccs; + + /** + * TNCCS send message function + */ + tnccs_send_message_t send_message; + + /** + * TNCCS request handshake retry flag + */ + bool *request_handshake_retry; + + /** + * collection of IMV recommendations + */ + recommendations_t *recs; +}; + +/** + * private data of tnc_tnccs_manager + */ +struct private_tnc_tnccs_manager_t { + + /** + * public functions + */ + tnccs_manager_t public; + + /** + * list of TNCCS protocol entries + */ + linked_list_t *protocols; + + /** + * rwlock to lock the TNCCS protocol entries + */ + rwlock_t *protocol_lock; + + /** + * connection ID counter + */ + TNC_ConnectionID connection_id; + + /** + * list of TNCCS connection entries + */ + linked_list_t *connections; + + /** + * rwlock to lock TNCCS connection entries + */ + rwlock_t *connection_lock; + +}; + +METHOD(tnccs_manager_t, add_method, void, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, + tnccs_constructor_t constructor) +{ + tnccs_entry_t *entry; + + entry = malloc_thing(tnccs_entry_t); + entry->type = type; + entry->constructor = constructor; + + this->protocol_lock->write_lock(this->protocol_lock); + this->protocols->insert_last(this->protocols, entry); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, remove_method, void, + private_tnc_tnccs_manager_t *this, tnccs_constructor_t constructor) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + + this->protocol_lock->write_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (constructor == entry->constructor) + { + this->protocols->remove_at(this->protocols, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); +} + +METHOD(tnccs_manager_t, create_instance, tnccs_t*, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server) +{ + enumerator_t *enumerator; + tnccs_entry_t *entry; + tnccs_t *protocol = NULL; + + this->protocol_lock->read_lock(this->protocol_lock); + enumerator = this->protocols->create_enumerator(this->protocols); + while (enumerator->enumerate(enumerator, &entry)) + { + if (type == entry->type) + { + protocol = entry->constructor(is_server); + if (protocol) + { + break; + } + } + } + enumerator->destroy(enumerator); + this->protocol_lock->unlock(this->protocol_lock); + + return protocol; +} + +METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID, + private_tnc_tnccs_manager_t *this, tnccs_type_t type, tnccs_t *tnccs, + tnccs_send_message_t send_message, bool* request_handshake_retry, + recommendations_t **recs) +{ + tnccs_connection_entry_t *entry; + + entry = malloc_thing(tnccs_connection_entry_t); + entry->type = type; + entry->tnccs = tnccs; + entry->send_message = send_message; + entry->request_handshake_retry = request_handshake_retry; + if (recs) + { + /* we assume a TNC Server needing recommendations from IMVs */ + if (!tnc->imvs) + { + DBG1(DBG_TNC, "no IMV manager available!"); + free(entry); + return 0; + } + entry->recs = tnc->imvs->create_recommendations(tnc->imvs); + *recs = entry->recs; + } + else + { + /* we assume a TNC Client */ + if (!tnc->imcs) + { + DBG1(DBG_TNC, "no IMC manager available!"); + free(entry); + return 0; + } + entry->recs = NULL; + } + this->connection_lock->write_lock(this->connection_lock); + entry->id = ++this->connection_id; + this->connections->insert_last(this->connections, entry); + this->connection_lock->unlock(this->connection_lock); + + DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id); + return entry->id; +} + +METHOD(tnccs_manager_t, remove_connection, void, + private_tnc_tnccs_manager_t *this, TNC_ConnectionID id, bool is_server) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + if (is_server) + { + if (tnc->imvs) + { + tnc->imvs->notify_connection_change(tnc->imvs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + else + { + if (tnc->imcs) + { + tnc->imcs->notify_connection_change(tnc->imcs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + + this->connection_lock->write_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + this->connections->remove_at(this->connections, enumerator); + if (entry->recs) + { + entry->recs->destroy(entry->recs); + } + free(entry); + DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id); + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); +} + +METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result, + private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_RetryReason reason) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + + if (id == TNC_CONNECTIONID_ANY) + { + DBG2(DBG_TNC, "%s %u requests handshake retry for all connections " + "(reason: %u)", is_imc ? "IMC":"IMV", reason); + } + else + { + DBG2(DBG_TNC, "%s %u requests handshake retry for Connection ID %u " + "(reason: %u)", is_imc ? "IMC":"IMV", imcv_id, id, reason); + } + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == TNC_CONNECTIONID_ANY || id == entry->id) + { + *entry->request_handshake_retry = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + return TNC_RESULT_SUCCESS; +} + +METHOD(tnccs_manager_t, send_message, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_UInt32 msg_flags, + TNC_BufferReference msg, + TNC_UInt32 msg_len, + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype) + +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + tnccs_send_message_t send_message = NULL; + tnccs_t *tnccs = NULL; + + if (msg_vid == TNC_VENDORID_ANY || msg_subtype == TNC_SUBTYPE_ANY) + { + DBG1(DBG_TNC, "not sending message of invalid type 0x%02x/0x%08x", + msg_vid, msg_subtype); + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + tnccs = entry->tnccs; + send_message = entry->send_message; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (tnccs && send_message) + { + return send_message(tnccs, imc_id, imv_id, msg_flags, msg, msg_len, + msg_vid, msg_subtype); + } + return TNC_RESULT_FATAL; +} + +METHOD(tnccs_manager_t, provide_recommendation, TNC_Result, + private_tnc_tnccs_manager_t *this, TNC_IMVID imv_id, + TNC_ConnectionID id, + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + recs->provide_recommendation(recs, imv_id, rec, eval); + return TNC_RESULT_SUCCESS; + } + return TNC_RESULT_FATAL; +} + +/** + * Write the value of a boolean attribute into the buffer + */ +static TNC_Result bool_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + bool value) +{ + *value_len = 1; + + if (buffer && buffer_len > 0) + { + *buffer = value ? 0x01 : 0x00; + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + +/** + * Write the value of an u_int32_t attribute into the buffer + */ +static TNC_Result uint_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + u_int32_t value) +{ + *value_len = sizeof(u_int32_t); + + if (buffer && buffer_len >= *value_len) + { + htoun32(buffer, value); + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + +/** + * Write the value of string attribute into the buffer + */ +static TNC_Result str_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + char *value) +{ + *value_len = 1 + strlen(value); + + if (buffer && buffer_len >= *value_len) + { + snprintf(buffer, buffer_len, "%s", value); + return TNC_RESULT_SUCCESS; + } + else + { + return TNC_RESULT_INVALID_PARAMETER; + } +} + +METHOD(tnccs_manager_t, get_attribute, TNC_Result, + private_tnc_tnccs_manager_t *this, bool is_imc, + TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + bool attribute_match = FALSE, entry_found = FALSE; + + if (is_imc) + { + switch (attribute_id) + { + /* these attributes are unsupported */ + case TNC_ATTRIBUTEID_SOHR: + case TNC_ATTRIBUTEID_SSOHR: + return TNC_RESULT_INVALID_PARAMETER; + + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PRIMARY_IMC_ID: + attribute_match = TRUE; + break; + + /* these attributes are yet to be matched */ + default: + break; + } + } + else + { + switch (attribute_id) + { + /* these attributes are unsupported or invalid */ + case TNC_ATTRIBUTEID_REASON_STRING: + case TNC_ATTRIBUTEID_REASON_LANGUAGE: + case TNC_ATTRIBUTEID_SOH: + case TNC_ATTRIBUTEID_SSOH: + return TNC_RESULT_INVALID_PARAMETER; + + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PRIMARY_IMV_ID: + attribute_match = TRUE; + break; + + /* these attributes are yet to be matched */ + default: + break; + } + } + + if (!attribute_match) + { + switch (attribute_id) + { + /* these attributes are supported */ + case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE: + case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS: + case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE: + case TNC_ATTRIBUTEID_HAS_LONG_TYPES: + case TNC_ATTRIBUTEID_HAS_EXCLUSIVE: + case TNC_ATTRIBUTEID_HAS_SOH: + case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL: + case TNC_ATTRIBUTEID_IFTNCCS_VERSION: + case TNC_ATTRIBUTEID_IFT_PROTOCOL: + case TNC_ATTRIBUTEID_IFT_VERSION: + break; + + /* these attributes are unsupported or unknown */ + case TNC_ATTRIBUTEID_DHPN: + case TNC_ATTRIBUTEID_TLS_UNIQUE: + default: + return TNC_RESULT_INVALID_PARAMETER; + } + } + + /* attributes specific to the TNCC or TNCS are unsupported */ + if (id == TNC_CONNECTIONID_ANY) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + entry_found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (!entry_found) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + switch (attribute_id) + { + case TNC_ATTRIBUTEID_PREFERRED_LANGUAGE: + { + recommendations_t *recs; + chunk_t pref_lang; + + recs = entry->recs; + if (!recs) + { + return TNC_RESULT_INVALID_PARAMETER; + } + pref_lang = recs->get_preferred_language(recs); + if (pref_lang.len == 0) + { + return TNC_RESULT_INVALID_PARAMETER; + } + *value_len = pref_lang.len; + if (buffer && buffer_len >= pref_lang.len) + { + memcpy(buffer, pref_lang.ptr, pref_lang.len); + } + return TNC_RESULT_SUCCESS; + } + case TNC_ATTRIBUTEID_MAX_ROUND_TRIPS: + return uint_attribute(buffer_len, buffer, value_len, 0xffffffff); + case TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE: + return uint_attribute(buffer_len, buffer, value_len, 0x00000000); + case TNC_ATTRIBUTEID_HAS_LONG_TYPES: + case TNC_ATTRIBUTEID_HAS_EXCLUSIVE: + return bool_attribute(buffer_len, buffer, value_len, + entry->type == TNCCS_2_0); + case TNC_ATTRIBUTEID_HAS_SOH: + return bool_attribute(buffer_len, buffer, value_len, + entry->type == TNCCS_SOH); + case TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL: + { + char *protocol; + + switch (entry->type) + { + case TNCCS_1_1: + case TNCCS_2_0: + protocol = "IF-TNCCS"; + break; + case TNCCS_SOH: + protocol = "IF-TNCCS-SOH"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, protocol); + } + case TNC_ATTRIBUTEID_IFTNCCS_VERSION: + { + char *version; + + switch (entry->type) + { + case TNCCS_1_1: + version = "1.1"; + break; + case TNCCS_2_0: + version = "2.0"; + break; + case TNCCS_SOH: + version = "1.0"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, version); + } + case TNC_ATTRIBUTEID_IFT_PROTOCOL: + return str_attribute(buffer_len, buffer, value_len, + "IF-T for Tunneled EAP"); + case TNC_ATTRIBUTEID_IFT_VERSION: + return str_attribute(buffer_len, buffer, value_len, "1.1"); + default: + return TNC_RESULT_INVALID_PARAMETER; + } +} + +METHOD(tnccs_manager_t, set_attribute, TNC_Result, + private_tnc_tnccs_manager_t *this, bool is_imc, + TNC_UInt32 imcv_id, + TNC_ConnectionID id, + TNC_AttributeID attribute_id, + TNC_UInt32 buffer_len, + TNC_BufferReference buffer) +{ + enumerator_t *enumerator; + tnccs_connection_entry_t *entry; + recommendations_t *recs = NULL; + + if (is_imc || id == TNC_CONNECTIONID_ANY || + (attribute_id != TNC_ATTRIBUTEID_REASON_STRING && + attribute_id != TNC_ATTRIBUTEID_REASON_LANGUAGE)) + { + return TNC_RESULT_INVALID_PARAMETER; + } + + this->connection_lock->read_lock(this->connection_lock); + enumerator = this->connections->create_enumerator(this->connections); + while (enumerator->enumerate(enumerator, &entry)) + { + if (id == entry->id) + { + recs = entry->recs; + break; + } + } + enumerator->destroy(enumerator); + this->connection_lock->unlock(this->connection_lock); + + if (recs) + { + chunk_t attribute = { buffer, buffer_len }; + + if (attribute_id == TNC_ATTRIBUTEID_REASON_STRING) + { + return recs->set_reason_string(recs, imcv_id, attribute); + } + else + { + return recs->set_reason_language(recs, imcv_id, attribute); + } + } + return TNC_RESULT_INVALID_PARAMETER; +} + +METHOD(tnccs_manager_t, destroy, void, + private_tnc_tnccs_manager_t *this) +{ + this->protocols->destroy_function(this->protocols, free); + this->protocol_lock->destroy(this->protocol_lock); + this->connections->destroy_function(this->connections, free); + this->connection_lock->destroy(this->connection_lock); + free(this); +} + +/* + * See header + */ +tnccs_manager_t *tnc_tnccs_manager_create() +{ + private_tnc_tnccs_manager_t *this; + + INIT(this, + .public = { + .add_method = _add_method, + .remove_method = _remove_method, + .create_instance = _create_instance, + .create_connection = _create_connection, + .remove_connection = _remove_connection, + .request_handshake_retry = _request_handshake_retry, + .send_message = _send_message, + .provide_recommendation = _provide_recommendation, + .get_attribute = _get_attribute, + .set_attribute = _set_attribute, + .destroy = _destroy, + }, + .protocols = linked_list_create(), + .connections = linked_list_create(), + .protocol_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .connection_lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h new file mode 100644 index 000000000..dd5149846 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * @defgroup tnc_tnccs_manager tnc_tnccs_manager + * @{ @ingroup tnc_tnccs + */ + +#ifndef TNC_TNCCS_MANAGER_H_ +#define TNC_TNCCS_MANAGER_H_ + +#include <tnc/tnccs/tnccs_manager.h> + +/** + * Create a TNCCS manager instance. + */ +tnccs_manager_t *tnc_tnccs_manager_create(); + +#endif /** TNC_TNCCS_MANAGER_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c new file mode 100644 index 000000000..a44319ed1 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.c @@ -0,0 +1,98 @@ +/* + * 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_tnccs_plugin.h" +#include "tnc_tnccs_manager.h" + +#include <tnc/tnc.h> + +#include <debug.h> + +typedef struct private_tnc_tnccs_plugin_t private_tnc_tnccs_plugin_t; + +/** + * Private data of a tnc_tnccs_plugin_t object. + */ +struct private_tnc_tnccs_plugin_t { + + /** + * Public interface. + */ + tnc_tnccs_plugin_t public; + +}; + + +METHOD(plugin_t, get_name, char*, + private_tnc_tnccs_plugin_t *this) +{ + return "tnc-tnccs"; +} + +METHOD(plugin_t, get_features, int, + private_tnc_tnccs_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnc_manager_register, tnc_tnccs_manager_create), + PLUGIN_PROVIDE(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_tnc_tnccs_plugin_t *this) +{ + libtnccs_deinit(); + free(this); +} + +/* + * see header file + */ +plugin_t *tnc_tnccs_plugin_create(void) +{ + private_tnc_tnccs_plugin_t *this; + + if (lib->integrity) + { + if (lib->integrity->check(lib->integrity, "libtnccs", libtnccs_init)) + { + DBG1(DBG_LIB, + "lib 'libtnccs': passed file and segment integrity tests"); + } + else + { + DBG1(DBG_LIB, + "lib 'libtnccs': failed integrity tests"); + return NULL; + } + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + libtnccs_init(); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h new file mode 100644 index 000000000..f935fa462 --- /dev/null +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_plugin.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/** + * @defgroup tnc_tnccs tnc_tnccs + * @ingroup cplugins + * + * @defgroup tnc_tnccs_plugin tnc_tnccs_plugin + * @{ @ingroup tnc_tnccs + */ + +#ifndef TNC_TNCCS_PLUGIN_H_ +#define TNC_TNCCS_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct tnc_tnccs_plugin_t tnc_tnccs_plugin_t; + +/** + * TNCCS manager plugin + */ +struct tnc_tnccs_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** TNC_TNCCS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/Makefile.am b/src/libcharon/plugins/tnccs_11/Makefile.am index 1042c3514..c205692d4 100644 --- a/src/libcharon/plugins/tnccs_11/Makefile.am +++ b/src/libcharon/plugins/tnccs_11/Makefile.am @@ -1,6 +1,10 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS} +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs \ + ${xml_CFLAGS} AM_CFLAGS = -rdynamic @@ -10,6 +14,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-11.la else plugin_LTLIBRARIES = libstrongswan-tnccs-11.la +libstrongswan_tnccs_11_la_LIBADD += \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_tnccs_11_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnccs_11/Makefile.in b/src/libcharon/plugins/tnccs_11/Makefile.in index 308dd57ca..1902d1f93 100644 --- a/src/libcharon/plugins/tnccs_11/Makefile.in +++ b/src/libcharon/plugins/tnccs_11/Makefile.in @@ -34,6 +34,10 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@MONOLITHIC_FALSE@am__append_1 = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + subdir = src/libcharon/plugins/tnccs_11 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -75,7 +79,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = -libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +libstrongswan_tnccs_11_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__append_1) am_libstrongswan_tnccs_11_la_OBJECTS = tnccs_11_plugin.lo tnccs_11.lo \ tnccs_batch.lo tnccs_msg.lo imc_imv_msg.lo tnccs_error_msg.lo \ tnccs_preferred_language_msg.lo tnccs_reason_strings_msg.lo \ @@ -198,6 +203,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -206,6 +214,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -222,11 +231,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -270,6 +281,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -280,11 +292,15 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls ${xml_CFLAGS} +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs \ + ${xml_CFLAGS} AM_CFLAGS = -rdynamic -libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} +libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} $(am__append_1) @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-11.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-11.la libstrongswan_tnccs_11_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c index 0f6f3a675..c9397722b 100644 --- a/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c +++ b/src/libcharon/plugins/tnccs_11/batch/tnccs_batch.c @@ -16,10 +16,11 @@ #include "tnccs_batch.h" #include "messages/tnccs_error_msg.h" -#include <debug.h> -#include <utils/linked_list.h> #include <tnc/tnccs/tnccs.h> +#include <utils/linked_list.h> +#include <debug.h> + #include <libxml/parser.h> typedef struct private_tnccs_batch_t private_tnccs_batch_t; diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c index f24c0dac9..fa570aae9 100644 --- a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c +++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.c @@ -16,8 +16,9 @@ #include "imc_imv_msg.h" #include <tnc/tnccs/tnccs.h> -#include <debug.h> + #include <utils/lexparser.h> +#include <debug.h> typedef struct private_imc_imv_msg_t private_imc_imv_msg_t; diff --git a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h index 02f07199f..3477fa74e 100644 --- a/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h +++ b/src/libcharon/plugins/tnccs_11/messages/imc_imv_msg.h @@ -25,7 +25,7 @@ typedef struct imc_imv_msg_t imc_imv_msg_t; #include "tnccs_msg.h" -#include <tnc/tncif.h> +#include <tncif.h> /** * Classs representing the PB-PA message type. diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h index d301ab2bb..c2de7fe4d 100644 --- a/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_preferred_language_msg.h @@ -25,7 +25,7 @@ typedef struct tnccs_preferred_language_msg_t tnccs_preferred_language_msg_t; #include "tnccs_msg.h" -#include <tnc/tncif.h> +#include <tncif.h> /** * Class representing the TNCCS-PreferredLanguage message type diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c index d4b5d9bf9..af60a4b3a 100644 --- a/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_reason_strings_msg.c @@ -14,6 +14,7 @@ */ #include "tnccs_reason_strings_msg.h" +#include "tnccs_error_msg.h" #include <debug.h> @@ -85,6 +86,10 @@ tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node, linked_list_t *errors) { private_tnccs_reason_strings_msg_t *this; + char *error_msg, *lang_string, *reason_string; + tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH; + tnccs_msg_t *msg; + xmlNodePtr child; INIT(this, .public = { @@ -99,7 +104,45 @@ tnccs_msg_t *tnccs_reason_strings_msg_create_from_node(xmlNodePtr node, .node = node, ); + if (xmlStrcmp(node->name, (const xmlChar*)"TNCCS-ReasonStrings")) + { + error_msg = "TNCCS-ReasonStrings tag expected"; + goto fatal; + } + + child = node->xmlChildrenNode; + while (child) + { + if (xmlIsBlankNode(child)) + { + child = child->next; + continue; + } + if (xmlStrcmp(child->name, (const xmlChar*)"ReasonString")) + { + error_msg = "ReasonString tag expected"; + goto fatal; + } + break; + } + + lang_string = (char*)xmlGetProp(child, (const xmlChar*)"lang"); + if (!lang_string) + { + lang_string = ""; + } + this->language = chunk_create(strdup(lang_string), strlen(lang_string)); + + reason_string = (char*)xmlNodeGetContent(child); + this->reason = chunk_create(strdup(reason_string), strlen(reason_string)); + return &this->public.tnccs_msg_interface; + +fatal: + msg = tnccs_error_msg_create(error_type, error_msg); + errors->insert_last(errors, msg); + destroy(this); + return NULL; } /** @@ -140,10 +183,12 @@ tnccs_msg_t *tnccs_reason_strings_msg_create(chunk_t reason, chunk_t language) n2 = xmlNewNode(NULL, BAD_CAST enum_to_name(tnccs_msg_type_names, this->type)); /* could add multiple reasons here, if we had them */ + n3 = xmlNewNode(NULL, BAD_CAST "ReasonString"); xmlNewProp(n3, BAD_CAST "xml:lang", BAD_CAST this->language.ptr); xmlNodeSetContent(n3, BAD_CAST this->reason.ptr); xmlAddChild(n2, n3); + xmlAddChild(n, n2); return &this->public.tnccs_msg_interface; } diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c index adc7b54b9..610224242 100644 --- a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.c @@ -128,7 +128,7 @@ tnccs_msg_t *tnccs_recommendation_msg_create_from_node(xmlNodePtr node, fatal: msg = tnccs_error_msg_create(error_type, error_msg); errors->insert_last(errors, msg); - _destroy(this); + destroy(this); return NULL; } diff --git a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h index 685049e95..3a67a3b32 100644 --- a/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h +++ b/src/libcharon/plugins/tnccs_11/messages/tnccs_recommendation_msg.h @@ -25,7 +25,7 @@ typedef struct tnccs_recommendation_msg_t tnccs_recommendation_msg_t; #include "tnccs_msg.h" -#include <tnc/tncifimv.h> +#include <tncifimv.h> /** * Class representing the TNCCS-Recommendation message type diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index 86f1c269f..3673221e5 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -22,12 +22,17 @@ #include "messages/tnccs_reason_strings_msg.h" #include "messages/tnccs_recommendation_msg.h" -#include <daemon.h> +#include <tncif_names.h> +#include <tncif_pa_subtypes.h> + +#include <tnc/tnc.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/imv/imv_manager.h> +#include <tnc/tnccs/tnccs.h> +#include <tnc/tnccs/tnccs_manager.h> + #include <debug.h> #include <threading/mutex.h> -#include <tnc/tncif.h> -#include <tnc/tncifimv.h> -#include <tnc/tnccs/tnccs.h> typedef struct private_tnccs_11_t private_tnccs_11_t; @@ -90,15 +95,20 @@ struct private_tnccs_11_t { * Set of IMV recommendations (TNC Server only) */ recommendations_t *recs; + }; METHOD(tnccs_t, send_msg, TNC_Result, private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_UInt32 msg_flags, TNC_BufferReference msg, TNC_UInt32 msg_len, - TNC_MessageType msg_type) + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype) { tnccs_msg_t *tnccs_msg; + TNC_MessageType msg_type; + enum_name_t *pa_subtype_names; if (!this->send_msg) { @@ -107,6 +117,24 @@ METHOD(tnccs_t, send_msg, TNC_Result, this->is_server ? imv_id : imc_id); return TNC_RESULT_ILLEGAL_OPERATION; } + if (msg_vid > TNC_VENDORID_ANY || msg_subtype > TNC_SUBTYPE_ANY) + { + return TNC_RESULT_NO_LONG_MESSAGE_TYPES; + } + msg_type = (msg_vid << 8) | msg_subtype; + + pa_subtype_names = get_pa_subtype_names(msg_vid); + if (pa_subtype_names) + { + DBG2(DBG_TNC, "creating IMC-IMV message type '%N/%N' 0x%06x/0x%02x", + pen_names, msg_vid, pa_subtype_names, msg_subtype, + msg_vid, msg_subtype); + } + else + { + DBG2(DBG_TNC, "creating IMC-IMV message type '%N' 0x%06x/0x%02x", + pen_names, msg_vid, msg_vid, msg_subtype); + } tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len)); /* adding an IMC-IMV Message to TNCCS batch */ @@ -132,23 +160,40 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) imc_imv_msg_t *imc_imv_msg; TNC_MessageType msg_type; chunk_t msg_body; + u_int32_t msg_vid, msg_subtype; + enum_name_t *pa_subtype_names; imc_imv_msg = (imc_imv_msg_t*)msg; msg_type = imc_imv_msg->get_msg_type(imc_imv_msg); msg_body = imc_imv_msg->get_msg_body(imc_imv_msg); + msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; - DBG2(DBG_TNC, "handling IMC_IMV message type 0x%08x", msg_type); + pa_subtype_names = get_pa_subtype_names(msg_vid); + if (pa_subtype_names) + { + DBG2(DBG_TNC, "handling IMC-IMV message type '%N/%N' 0x%06x/0x%02x", + pen_names, msg_vid, pa_subtype_names, msg_subtype, + msg_vid, msg_subtype); + } + else + { + DBG2(DBG_TNC, "handling IMC-IMV message type '%N' 0x%06x/0x%02x", + pen_names, msg_vid, msg_vid, msg_subtype); + } this->send_msg = TRUE; if (this->is_server) { - charon->imvs->receive_message(charon->imvs, - this->connection_id, msg_body.ptr, msg_body.len, msg_type); + tnc->imvs->receive_message(tnc->imvs, this->connection_id, + FALSE, msg_body.ptr, msg_body.len, + msg_vid, msg_subtype, 0, TNC_IMVID_ANY); } else { - charon->imcs->receive_message(charon->imcs, - this->connection_id, msg_body.ptr, msg_body.len,msg_type); + tnc->imcs->receive_message(tnc->imcs, this->connection_id, + FALSE, msg_body.ptr, msg_body.len, + msg_vid, msg_subtype, 0, TNC_IMCID_ANY); } this->send_msg = FALSE; break; @@ -181,8 +226,8 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) default: state = TNC_CONNECTION_STATE_ACCESS_NONE; } - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, state); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + state); this->delete_state = TRUE; break; } @@ -221,9 +266,9 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) reason_msg = (tnccs_reason_strings_msg_t*)msg; reason_string = reason_msg->get_reason(reason_msg, &reason_lang); - DBG2(DBG_TNC, "reason string is '%.*s", reason_string.len, + DBG2(DBG_TNC, "reason string is '%.*s'", reason_string.len, reason_string.ptr); - DBG2(DBG_TNC, "reason language is '%.*s", reason_lang.len, + DBG2(DBG_TNC, "reason language is '%.*s'", reason_lang.len, reason_lang.ptr); break; } @@ -243,17 +288,17 @@ METHOD(tls_t, process, status_t, if (this->is_server && !this->connection_id) { - this->connection_id = charon->tnccs->create_connection(charon->tnccs, - (tnccs_t*)this, _send_msg, + this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, + TNCCS_1_1, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, &this->recs); if (!this->connection_id) { return FAILED; } - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_CREATE); - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, + TNC_CONNECTION_STATE_CREATE); + tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, + TNC_CONNECTION_STATE_HANDSHAKE); } data = chunk_create(buf, buflen); @@ -304,11 +349,11 @@ METHOD(tls_t, process, status_t, this->send_msg = TRUE; if (this->is_server) { - charon->imvs->batch_ending(charon->imvs, this->connection_id); + tnc->imvs->batch_ending(tnc->imvs, this->connection_id); } else { - charon->imcs->batch_ending(charon->imcs, this->connection_id); + tnc->imcs->batch_ending(tnc->imcs, this->connection_id); } this->send_msg = FALSE; } @@ -331,7 +376,7 @@ static void check_and_build_recommendation(private_tnccs_11_t *this) if (!this->recs->have_recommendation(this->recs, &rec, &eval)) { - charon->imvs->solicit_recommendation(charon->imvs, this->connection_id); + tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id); } if (this->recs->have_recommendation(this->recs, &rec, &eval)) { @@ -351,6 +396,7 @@ static void check_and_build_recommendation(private_tnccs_11_t *this) this->batch->add_msg(this->batch, msg); } enumerator->destroy(enumerator); + this->recs->clear_reasons(this->recs); /* we have reache the final state */ this->delete_state = TRUE; @@ -368,8 +414,8 @@ METHOD(tls_t, build, status_t, tnccs_msg_t *msg; char *pref_lang; - this->connection_id = charon->tnccs->create_connection(charon->tnccs, - (tnccs_t*)this, _send_msg, + this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, + TNCCS_1_1, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, NULL); if (!this->connection_id) { @@ -377,19 +423,19 @@ METHOD(tls_t, build, status_t, } /* Create TNCCS-PreferredLanguage message */ - pref_lang = charon->imcs->get_preferred_language(charon->imcs); + pref_lang = tnc->imcs->get_preferred_language(tnc->imcs); msg = tnccs_preferred_language_msg_create(pref_lang); this->mutex->lock(this->mutex); this->batch = tnccs_batch_create(this->is_server, ++this->batch_id); this->batch->add_msg(this->batch, msg); this->mutex->unlock(this->mutex); - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_CREATE); - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + TNC_CONNECTION_STATE_CREATE); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + TNC_CONNECTION_STATE_HANDSHAKE); this->send_msg = TRUE; - charon->imcs->begin_handshake(charon->imcs, this->connection_id); + tnc->imcs->begin_handshake(tnc->imcs, this->connection_id); this->send_msg = FALSE; } @@ -456,7 +502,7 @@ METHOD(tls_t, is_complete, bool, if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) { - return charon->imvs->enforce_recommendation(charon->imvs, rec, eval); + return tnc->imvs->enforce_recommendation(tnc->imvs, rec, eval); } else { @@ -473,8 +519,8 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_11_t *this) { - charon->tnccs->remove_connection(charon->tnccs, this->connection_id, - this->is_server); + tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, + this->is_server); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); free(this); diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c index 9ec91f006..cd95afb1e 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c @@ -16,7 +16,7 @@ #include "tnccs_11_plugin.h" #include "tnccs_11.h" -#include <daemon.h> +#include <tnc/tnccs/tnccs_manager.h> METHOD(plugin_t, get_name, char*, tnccs_11_plugin_t *this) @@ -24,11 +24,23 @@ METHOD(plugin_t, get_name, char*, return "tnccs-11"; } +METHOD(plugin_t, get_features, int, + tnccs_11_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnccs_method_register, tnccs_11_create), + PLUGIN_PROVIDE(CUSTOM, "tnccs-1.1"), + PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), + PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, tnccs_11_plugin_t *this) { - charon->tnccs->remove_method(charon->tnccs, - (tnccs_constructor_t)tnccs_11_create); free(this); } @@ -42,14 +54,11 @@ plugin_t *tnccs_11_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_1_1, - (tnccs_constructor_t)tnccs_11_create); - return &this->plugin; } diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am index d72fd3e34..ec17e6412 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.am +++ b/src/libcharon/plugins/tnccs_20/Makefile.am @@ -1,6 +1,9 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @@ -8,7 +11,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-20.la else plugin_LTLIBRARIES = libstrongswan-tnccs-20.la -libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libstrongswan_tnccs_20_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_tnccs_20_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in index bbfcc2760..b0078f338 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.in +++ b/src/libcharon/plugins/tnccs_20/Makefile.in @@ -75,7 +75,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) @MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_DEPENDENCIES = \ -@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la am_libstrongswan_tnccs_20_la_OBJECTS = tnccs_20_plugin.lo tnccs_20.lo \ pb_tnc_batch.lo pb_tnc_msg.lo pb_experimental_msg.lo \ pb_pa_msg.lo pb_assessment_result_msg.lo \ @@ -200,6 +201,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -208,6 +212,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -224,11 +229,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -272,6 +279,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -282,13 +290,19 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-20.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-20.la -@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@libstrongswan_tnccs_20_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + libstrongswan_tnccs_20_la_SOURCES = \ tnccs_20_plugin.h tnccs_20_plugin.c tnccs_20.h tnccs_20.c \ batch/pb_tnc_batch.h batch/pb_tnc_batch.c \ diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c index 3f38543ed..c6a4bb599 100644 --- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c @@ -18,12 +18,14 @@ #include "messages/pb_error_msg.h" #include "state_machine/pb_tnc_state_machine.h" -#include <debug.h> -#include <utils/linked_list.h> -#include <tls_writer.h> -#include <tls_reader.h> #include <tnc/tnccs/tnccs.h> +#include <utils/linked_list.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <pen/pen.h> +#include <debug.h> + ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE, "CDATA", "SDATA", @@ -142,7 +144,7 @@ METHOD(pb_tnc_batch_t, build, void, enumerator_t *enumerator; pb_tnc_msg_type_t msg_type; pb_tnc_msg_t *msg; - tls_writer_t *writer; + bio_writer_t *writer; /* compute total PB-TNC batch size by summing over all messages */ batch_len = PB_TNC_BATCH_HEADER_SIZE; @@ -156,7 +158,7 @@ METHOD(pb_tnc_batch_t, build, void, enumerator->destroy(enumerator); /* build PB-TNC batch header */ - writer = tls_writer_create(batch_len); + writer = bio_writer_create(batch_len); writer->write_uint8 (writer, PB_TNC_VERSION); writer->write_uint8 (writer, this->is_server ? PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE); @@ -178,7 +180,7 @@ METHOD(pb_tnc_batch_t, build, void, flags |= PB_TNC_FLAG_NOSKIP; } writer->write_uint8 (writer, flags); - writer->write_uint24(writer, IETF_VENDOR_ID); + writer->write_uint24(writer, PEN_IETF); writer->write_uint32(writer, msg_type); writer->write_uint32(writer, msg_len); writer->write_data (writer, msg_value); @@ -192,7 +194,7 @@ METHOD(pb_tnc_batch_t, build, void, static status_t process_batch_header(private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine) { - tls_reader_t *reader; + bio_reader_t *reader; pb_tnc_msg_t *msg; pb_error_msg_t *err_msg; u_int8_t version, flags, reserved, type; @@ -203,12 +205,12 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, { DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header", this->encoding.len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, 0); goto fatal; } - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint8 (reader, &version); reader->read_uint8 (reader, &flags); reader->read_uint8 (reader, &reserved); @@ -220,7 +222,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, if (version != PB_TNC_VERSION) { DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%01x", version); - msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create(TRUE, PEN_IETF, PB_ERROR_VERSION_NOT_SUPPORTED); err_msg = (pb_error_msg_t*)msg; err_msg->set_bad_version(err_msg, version); @@ -233,7 +235,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, { DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s", directionality ? "server" : "client"); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, 1); goto fatal; } @@ -243,7 +245,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, if (this->type > PB_BATCH_ROOF) { DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, 3); goto fatal; } @@ -252,7 +254,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, { DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N", pb_tnc_batch_type_names, this->type); - msg = pb_error_msg_create(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create(TRUE, PEN_IETF, PB_ERROR_UNEXPECTED_BATCH_TYPE); goto fatal; } @@ -262,7 +264,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, { DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes", this->encoding.len, batch_len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, 4); goto fatal; } @@ -277,7 +279,7 @@ fatal: static status_t process_tnc_msg(private_pb_tnc_batch_t *this) { - tls_reader_t *reader; + bio_reader_t *reader; pb_tnc_msg_t *pb_tnc_msg, *msg; u_int8_t flags; u_int32_t vendor_id, msg_type, msg_len, offset; @@ -291,12 +293,12 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) { DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header", data.len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset); goto fatal; } - reader = tls_reader_create(data); + reader = bio_reader_create(data); reader->read_uint8 (reader, &flags); reader->read_uint24(reader, &vendor_id); reader->read_uint32(reader, &msg_type); @@ -308,15 +310,15 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) if (msg_len > data.len) { DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset + 8); goto fatal; } - if (vendor_id == RESERVED_VENDOR_ID) + if (vendor_id == PEN_RESERVED) { - DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED); + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset + 1); goto fatal; @@ -326,19 +328,19 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) { DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved", PB_TNC_RESERVED_MSG_TYPE); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset + 4); goto fatal; } - if (vendor_id != IETF_VENDOR_ID || msg_type > PB_MSG_ROOF) + if (vendor_id != PEN_IETF || msg_type > PB_MSG_ROOF) { if (msg_len < PB_TNC_HEADER_SIZE) { DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length", msg_len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset + 8); goto fatal; } @@ -347,7 +349,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) { DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / " "Type 0x%08x)", vendor_id, msg_type); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset); goto fatal; } @@ -367,7 +369,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set", pb_tnc_msg_type_names, msg_type, pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not"); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset); goto fatal; } @@ -380,7 +382,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) pb_tnc_msg_type_names, msg_type, pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least", pb_tnc_msg_infos[msg_type].min_size, msg_len); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset); goto fatal; } @@ -393,7 +395,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) { DBG1(DBG_TNC,"reject %N message received from a PB-TNC client", pb_tnc_msg_type_names, msg_type); - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, PB_ERROR_INVALID_PARAMETER, this->offset); goto fatal; } @@ -415,8 +417,8 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) status = pb_tnc_msg->process(pb_tnc_msg, &offset); if (status == FAILED || status == VERIFY_ERROR) { - msg = pb_error_msg_create_with_offset(TRUE, IETF_VENDOR_ID, - PB_ERROR_INVALID_PARAMETER, this->offset); + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, + PB_ERROR_INVALID_PARAMETER, this->offset + offset); this->errors->insert_last(this->errors, msg); } if (status == FAILED) diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c index 41b9e31f6..fa3deddf6 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_access_recommendation_msg.c @@ -15,8 +15,8 @@ #include "pb_access_recommendation_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> #include <debug.h> ENUM(pb_access_recommendation_code_names, PB_REC_ACCESS_ALLOWED, PB_REC_QUARANTINED, @@ -80,10 +80,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t, METHOD(pb_tnc_msg_t, build, void, private_pb_access_recommendation_msg_t *this) { - tls_writer_t *writer; + bio_writer_t *writer; /* build message */ - writer = tls_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE); + writer = bio_writer_create(ACCESS_RECOMMENDATION_MSG_SIZE); writer->write_uint16(writer, ACCESS_RECOMMENDATION_RESERVED); writer->write_uint16(writer, this->recommendation); free(this->encoding.ptr); @@ -95,11 +95,11 @@ METHOD(pb_tnc_msg_t, build, void, METHOD(pb_tnc_msg_t, process, status_t, private_pb_access_recommendation_msg_t *this, u_int32_t *offset) { - tls_reader_t *reader; + bio_reader_t *reader; u_int16_t reserved; /* process message */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint16(reader, &reserved); reader->read_uint16(reader, &this->recommendation); reader->destroy(reader); diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c index c91e54176..0d558c0d4 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_assessment_result_msg.c @@ -15,9 +15,10 @@ #include "pb_assessment_result_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> -#include <tnc/tncifimv.h> +#include <tncifimv.h> + +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> #include <debug.h> typedef struct private_pb_assessment_result_msg_t private_pb_assessment_result_msg_t; @@ -75,10 +76,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t, METHOD(pb_tnc_msg_t, build, void, private_pb_assessment_result_msg_t *this) { - tls_writer_t *writer; + bio_writer_t *writer; /* build message */ - writer = tls_writer_create(ASSESSMENT_RESULT_MSG_SIZE); + writer = bio_writer_create(ASSESSMENT_RESULT_MSG_SIZE); writer->write_uint32(writer, this->assessment_result); free(this->encoding.ptr); this->encoding = writer->get_buf(writer); @@ -89,10 +90,10 @@ METHOD(pb_tnc_msg_t, build, void, METHOD(pb_tnc_msg_t, process, status_t, private_pb_assessment_result_msg_t *this, u_int32_t *offset) { - tls_reader_t *reader; + bio_reader_t *reader; /* process message */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint32(reader, &this->assessment_result); reader->destroy(reader); diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c index e1755c512..03e3cec92 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_error_msg.c @@ -15,11 +15,13 @@ #include "pb_error_msg.h" -#include <debug.h> -#include <tls_writer.h> -#include <tls_reader.h> #include <tnc/tnccs/tnccs.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <pen/pen.h> +#include <debug.h> + ENUM(pb_tnc_error_code_names, PB_ERROR_UNEXPECTED_BATCH_TYPE, PB_ERROR_VERSION_NOT_SUPPORTED, "Unexpected Batch Type", @@ -116,10 +118,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t, METHOD(pb_tnc_msg_t, build, void, private_pb_error_msg_t *this) { - tls_writer_t *writer; + bio_writer_t *writer; /* build message header */ - writer = tls_writer_create(ERROR_HEADER_SIZE); + writer = bio_writer_create(ERROR_HEADER_SIZE); writer->write_uint8 (writer, this->fatal ? ERROR_FLAG_FATAL : ERROR_FLAG_NONE); writer->write_uint24(writer, this->vendor_id); @@ -152,24 +154,25 @@ METHOD(pb_tnc_msg_t, process, status_t, { u_int8_t flags, max_version, min_version; u_int16_t reserved; - tls_reader_t *reader; + bio_reader_t *reader; if (this->encoding.len < ERROR_HEADER_SIZE) { DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes", pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE); + *offset = 0; return FAILED; } /* process message header */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint8 (reader, &flags); reader->read_uint24(reader, &this->vendor_id); reader->read_uint16(reader, &this->error_code); reader->read_uint16(reader, &reserved); this->fatal = (flags & ERROR_FLAG_FATAL) != ERROR_FLAG_NONE; - if (this->vendor_id == IETF_VENDOR_ID && reader->remaining(reader) == 4) + if (this->vendor_id == PEN_IETF && reader->remaining(reader) == 4) { if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED) { diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c index 9a94edf30..297cc8df7 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_language_preference_msg.c @@ -15,8 +15,8 @@ #include "pb_language_preference_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> #include <debug.h> typedef struct private_pb_language_preference_msg_t private_pb_language_preference_msg_t; diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c index 8315bfb76..1c4913e5e 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c @@ -17,22 +17,12 @@ #include "pb_pa_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> #include <tnc/tnccs/tnccs.h> -#include <debug.h> -ENUM(pa_tnc_subtype_names, PA_SUBTYPE_TESTING, PA_SUBTYPE_NEA_CLIENT, - "Testing", - "Operating System", - "Anti-Virus", - "Anti-Spyware", - "Anti-Malware", - "Firewall", - "IDPS", - "VPN", - "NEA Client" -); +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <pen/pen.h> +#include <debug.h> typedef struct private_pb_pa_msg_t private_pb_pa_msg_t; @@ -124,10 +114,10 @@ METHOD(pb_tnc_msg_t, build, void, private_pb_pa_msg_t *this) { chunk_t msg_header; - tls_writer_t *writer; + bio_writer_t *writer; /* build message header */ - writer = tls_writer_create(64); + writer = bio_writer_create(64); writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE); writer->write_uint24(writer, this->vendor_id); writer->write_uint32(writer, this->subtype); @@ -146,10 +136,10 @@ METHOD(pb_tnc_msg_t, process, status_t, { u_int8_t flags; size_t msg_body_len; - tls_reader_t *reader; + bio_reader_t *reader; /* process message header */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint8 (reader, &flags); reader->read_uint24(reader, &this->vendor_id); reader->read_uint32(reader, &this->subtype); @@ -166,9 +156,9 @@ METHOD(pb_tnc_msg_t, process, status_t, } reader->destroy(reader); - if (this->vendor_id == RESERVED_VENDOR_ID) + if (this->vendor_id == PEN_RESERVED) { - DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", RESERVED_VENDOR_ID); + DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED); *offset = 1; return FAILED; } @@ -221,12 +211,6 @@ METHOD(pb_pa_msg_t, get_exclusive_flag, bool, return this->excl; } -METHOD(pb_pa_msg_t, set_exclusive_flag, void, - private_pb_pa_msg_t *this, bool excl) -{ - this->excl = excl; -} - /** * See header */ @@ -247,7 +231,6 @@ pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data) .get_validator_id = _get_validator_id, .get_body = _get_body, .get_exclusive_flag = _get_exclusive_flag, - .set_exclusive_flag = _set_exclusive_flag, }, .type = PB_MSG_PA, .encoding = chunk_clone(data), @@ -261,7 +244,7 @@ pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data) */ pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, u_int16_t collector_id, u_int16_t validator_id, - chunk_t msg_body) + bool excl, chunk_t msg_body) { private_pb_pa_msg_t *this; @@ -279,13 +262,13 @@ pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, .get_validator_id = _get_validator_id, .get_body = _get_body, .get_exclusive_flag = _get_exclusive_flag, - .set_exclusive_flag = _set_exclusive_flag, }, .type = PB_MSG_PA, .vendor_id = vendor_id, .subtype = subtype, .collector_id = collector_id, .validator_id = validator_id, + .excl = excl, .msg_body = chunk_clone(msg_body), ); diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h index 366d790f6..d9db9a1ce 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.h @@ -21,32 +21,11 @@ #ifndef PB_PA_MSG_H_ #define PB_PA_MSG_H_ -typedef enum pa_tnc_subtype_t pa_tnc_subtype_t; typedef struct pb_pa_msg_t pb_pa_msg_t; #include "pb_tnc_msg.h" /** - * PA-TNC Subtypes as defined in section 3.5 of RFC 5792 - */ - enum pa_tnc_subtype_t { - PA_SUBTYPE_TESTING = 0, - PA_SUBTYPE_OPERATING_SYSTEM = 1, - PA_SUBTYPE_ANTI_VIRUS = 2, - PA_SUBTYPE_ANTI_SPYWARE = 3, - PA_SUBTYPE_ANTI_MALWARE = 4, - PA_SUBTYPE_FIREWALL = 5, - PA_SUBTYPE_IDPS = 6, - PA_SUBTYPE_VPN = 7, - PA_SUBTYPE_NEA_CLIENT = 8 -}; - -/** - * enum name for pa_tnc_subtype_t. - */ -extern enum_name_t *pa_tnc_subtype_names; - -/** * Class representing the PB-PA message type. */ struct pb_pa_msg_t { @@ -92,12 +71,6 @@ struct pb_pa_msg_t { */ bool (*get_exclusive_flag)(pb_pa_msg_t *this); - /** - * Set the exclusive flag - * - * @param excl vexclusive flag - */ - void (*set_exclusive_flag)(pb_pa_msg_t *this, bool excl); }; /** @@ -107,11 +80,12 @@ struct pb_pa_msg_t { * @param subtype PA Subtype * @param collector_id Posture Collector ID * @param validator_id Posture Validator ID + * @param excl Exclusive Flag * @param msg_body PA Message Body */ pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype, u_int16_t collector_id, u_int16_t validator_id, - chunk_t msg_body); + bool excl, chunk_t msg_body); /** * Create an unprocessed PB-PA message from raw data diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c index e361cf2b2..181ecf61b 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_reason_string_msg.c @@ -15,8 +15,8 @@ #include "pb_reason_string_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> #include <debug.h> typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t; @@ -81,10 +81,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t, METHOD(pb_tnc_msg_t, build, void, private_pb_reason_string_msg_t *this) { - tls_writer_t *writer; + bio_writer_t *writer; /* build message */ - writer = tls_writer_create(64); + writer = bio_writer_create(64); writer->write_data32(writer, this->reason_string); writer->write_data8 (writer, this->language_code); @@ -97,10 +97,10 @@ METHOD(pb_tnc_msg_t, build, void, METHOD(pb_tnc_msg_t, process, status_t, private_pb_reason_string_msg_t *this, u_int32_t *offset) { - tls_reader_t *reader; + bio_reader_t *reader; /* process message */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); if (!reader->read_data32(reader, &this->reason_string)) { DBG1(DBG_TNC, "could not parse reason string"); diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c index 79381a7b1..d213db313 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c @@ -15,8 +15,8 @@ #include "pb_remediation_parameters_msg.h" -#include <tls_writer.h> -#include <tls_reader.h> +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> #include <debug.h> ENUM(pb_tnc_remed_param_type_names, PB_REMEDIATION_URI, PB_REMEDIATION_STRING, @@ -106,10 +106,10 @@ METHOD(pb_tnc_msg_t, get_encoding, chunk_t, METHOD(pb_tnc_msg_t, build, void, private_pb_remediation_parameters_msg_t *this) { - tls_writer_t *writer; + bio_writer_t *writer; /* build message */ - writer = tls_writer_create(64); + writer = bio_writer_create(64); writer->write_uint32(writer, this->vendor_id); writer->write_uint32(writer, this->parameters_type); writer->write_data32(writer, this->remediation_string); @@ -124,10 +124,10 @@ METHOD(pb_tnc_msg_t, build, void, METHOD(pb_tnc_msg_t, process, status_t, private_pb_remediation_parameters_msg_t *this, u_int32_t *offset) { - tls_reader_t *reader; + bio_reader_t *reader; /* process message */ - reader = tls_reader_create(this->encoding); + reader = bio_reader_create(this->encoding); reader->read_uint32(reader, &this->vendor_id); reader->read_uint32(reader, &this->parameters_type); diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 9e2081d46..606fc529b 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Sansar Choinyanbuu - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2011 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -26,12 +26,17 @@ #include "messages/pb_language_preference_msg.h" #include "state_machine/pb_tnc_state_machine.h" +#include <tncif_names.h> +#include <tncif_pa_subtypes.h> + +#include <tnc/tnc.h> +#include <tnc/tnccs/tnccs_manager.h> +#include <tnc/imc/imc_manager.h> +#include <tnc/imv/imv_manager.h> + #include <debug.h> -#include <daemon.h> #include <threading/mutex.h> -#include <tnc/tncif.h> -#include <tnc/tncifimv.h> -#include <tnc/tnccs/tnccs.h> +#include <pen/pen.h> typedef struct private_tnccs_20_t private_tnccs_20_t; @@ -89,18 +94,21 @@ struct private_tnccs_20_t { * Set of IMV recommendations (TNC Server only) */ recommendations_t *recs; + }; METHOD(tnccs_t, send_msg, TNC_Result, private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, + TNC_UInt32 msg_flags, TNC_BufferReference msg, TNC_UInt32 msg_len, - TNC_MessageType msg_type) + TNC_VendorID msg_vid, + TNC_MessageSubtype msg_subtype) { - TNC_MessageSubtype msg_sub_type; - TNC_VendorID msg_vendor_id; pb_tnc_msg_t *pb_tnc_msg; pb_tnc_batch_type_t batch_type; + enum_name_t *pa_subtype_names; + bool excl; if (!this->send_msg) { @@ -109,12 +117,23 @@ METHOD(tnccs_t, send_msg, TNC_Result, this->is_server ? imv_id : imc_id); return TNC_RESULT_ILLEGAL_OPERATION; } + excl = (msg_flags & TNC_MESSAGE_FLAGS_EXCLUSIVE) != 0; - msg_sub_type = msg_type & TNC_SUBTYPE_ANY; - msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY; + pb_tnc_msg = pb_pa_msg_create(msg_vid, msg_subtype, imc_id, imv_id, + excl, chunk_create(msg, msg_len)); - pb_tnc_msg = pb_pa_msg_create(msg_vendor_id, msg_sub_type, imc_id, imv_id, - chunk_create(msg, msg_len)); + pa_subtype_names = get_pa_subtype_names(msg_vid); + if (pa_subtype_names) + { + DBG2(DBG_TNC, "creating PB-PA message type '%N/%N' 0x%06x/0x%08x", + pen_names, msg_vid, pa_subtype_names, msg_subtype, + msg_vid, msg_subtype); + } + else + { + DBG2(DBG_TNC, "creating PB-PA message type '%N' 0x%06x/0x%08x", + pen_names, msg_vid, msg_vid, msg_subtype); + } /* adding PA message to SDATA or CDATA batch only */ batch_type = this->is_server ? PB_BATCH_SDATA : PB_BATCH_CDATA; @@ -148,27 +167,44 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) case PB_MSG_PA: { pb_pa_msg_t *pa_msg; - TNC_MessageType msg_type; - u_int32_t vendor_id, subtype; + u_int32_t msg_vid, msg_subtype; + u_int16_t imc_id, imv_id; chunk_t msg_body; + bool excl; + enum_name_t *pa_subtype_names; pa_msg = (pb_pa_msg_t*)msg; - vendor_id = pa_msg->get_vendor_id(pa_msg, &subtype); - msg_type = (vendor_id << 8) | (subtype & 0xff); + msg_vid = pa_msg->get_vendor_id(pa_msg, &msg_subtype); msg_body = pa_msg->get_body(pa_msg); + imc_id = pa_msg->get_collector_id(pa_msg); + imv_id = pa_msg->get_validator_id(pa_msg); + excl = pa_msg->get_exclusive_flag(pa_msg); - DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type); + pa_subtype_names = get_pa_subtype_names(msg_vid); + if (pa_subtype_names) + { + DBG2(DBG_TNC, "handling PB-PA message type '%N/%N' 0x%06x/0x%08x", + pen_names, msg_vid, pa_subtype_names, msg_subtype, + msg_vid, msg_subtype); + } + else + { + DBG2(DBG_TNC, "handling PB-PA message type '%N' 0x%06x/0x%08x", + pen_names, msg_vid, msg_vid, msg_subtype); + } this->send_msg = TRUE; if (this->is_server) { - charon->imvs->receive_message(charon->imvs, - this->connection_id, msg_body.ptr, msg_body.len, msg_type); + tnc->imvs->receive_message(tnc->imvs, this->connection_id, + excl, msg_body.ptr, msg_body.len, + msg_vid, msg_subtype, imc_id, imv_id); } else { - charon->imcs->receive_message(charon->imcs, - this->connection_id, msg_body.ptr, msg_body.len,msg_type); + tnc->imcs->receive_message(tnc->imcs, this->connection_id, + excl, msg_body.ptr, msg_body.len, + msg_vid, msg_subtype, imv_id, imc_id); } this->send_msg = FALSE; break; @@ -205,8 +241,8 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) case PB_REC_QUARANTINED: state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; } - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, state); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + state); break; } case PB_MSG_REMEDIATION_PARAMETERS: @@ -231,7 +267,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) this->fatal_error = TRUE; } - if (vendor_id == IETF_VENDOR_ID) + if (vendor_id == PEN_IETF) { switch (error_code) { @@ -289,10 +325,10 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) reason_msg = (pb_reason_string_msg_t*)msg; reason_string = reason_msg->get_reason_string(reason_msg); language_code = reason_msg->get_language_code(reason_msg); - DBG2(DBG_TNC, "reason string is '%.*s", reason_string.len, - reason_string.ptr); - DBG2(DBG_TNC, "language code is '%.*s", language_code.len, - language_code.ptr); + DBG2(DBG_TNC, "reason string is '%.*s'", reason_string.len, + reason_string.ptr); + DBG2(DBG_TNC, "language code is '%.*s'", language_code.len, + language_code.ptr); break; } default: @@ -319,6 +355,11 @@ static void build_retry_batch(private_tnccs_20_t *this) pb_tnc_batch_type_names, this->batch->get_type(this->batch)); this->batch->destroy(this->batch); } + if (this->is_server) + { + tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, + TNC_CONNECTION_STATE_HANDSHAKE); + } this->batch = pb_tnc_batch_create(this->is_server, batch_retry_type); } @@ -333,17 +374,17 @@ METHOD(tls_t, process, status_t, if (this->is_server && !this->connection_id) { - this->connection_id = charon->tnccs->create_connection(charon->tnccs, - (tnccs_t*)this, _send_msg, + this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, + TNCCS_2_0, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, &this->recs); if (!this->connection_id) { return FAILED; } - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_CREATE); - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, + TNC_CONNECTION_STATE_CREATE); + tnc->imvs->notify_connection_change(tnc->imvs, this->connection_id, + TNC_CONNECTION_STATE_HANDSHAKE); } data = chunk_create(buf, buflen); @@ -372,10 +413,10 @@ METHOD(tls_t, process, status_t, else if (batch_type == PB_BATCH_SRETRY) { /* Restart the measurements */ - charon->imcs->notify_connection_change(charon->imcs, + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); this->send_msg = TRUE; - charon->imcs->begin_handshake(charon->imcs, this->connection_id); + tnc->imcs->begin_handshake(tnc->imcs, this->connection_id); this->send_msg = FALSE; } @@ -406,11 +447,11 @@ METHOD(tls_t, process, status_t, this->send_msg = TRUE; if (this->is_server) { - charon->imvs->batch_ending(charon->imvs, this->connection_id); + tnc->imvs->batch_ending(tnc->imvs, this->connection_id); } else { - charon->imcs->batch_ending(charon->imcs, this->connection_id); + tnc->imcs->batch_ending(tnc->imcs, this->connection_id); } this->send_msg = FALSE; } @@ -459,10 +500,11 @@ static void check_and_build_recommendation(private_tnccs_20_t *this) chunk_t reason, language; enumerator_t *enumerator; pb_tnc_msg_t *msg; + pb_access_recommendation_code_t pb_rec; if (!this->recs->have_recommendation(this->recs, &rec, &eval)) { - charon->imvs->solicit_recommendation(charon->imvs, this->connection_id); + tnc->imvs->solicit_recommendation(tnc->imvs, this->connection_id); } if (this->recs->have_recommendation(this->recs, &rec, &eval)) { @@ -472,10 +514,22 @@ static void check_and_build_recommendation(private_tnccs_20_t *this) this->batch->add_msg(this->batch, msg); /** - * IMV Action Recommendation and PB Access Recommendation codes - * are shifted by one. + * Map IMV Action Recommendation codes to PB Access Recommendation codes */ - msg = pb_access_recommendation_msg_create(rec + 1); + switch (rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + pb_rec = PB_REC_ACCESS_ALLOWED; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + pb_rec = PB_REC_QUARANTINED; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + default: + pb_rec = PB_REC_ACCESS_DENIED; + } + msg = pb_access_recommendation_msg_create(pb_rec); this->batch->add_msg(this->batch, msg); enumerator = this->recs->create_reason_enumerator(this->recs); @@ -485,6 +539,7 @@ static void check_and_build_recommendation(private_tnccs_20_t *this) this->batch->add_msg(this->batch, msg); } enumerator->destroy(enumerator); + this->recs->clear_reasons(this->recs); } } @@ -500,8 +555,8 @@ METHOD(tls_t, build, status_t, pb_tnc_msg_t *msg; char *pref_lang; - this->connection_id = charon->tnccs->create_connection(charon->tnccs, - (tnccs_t*)this, _send_msg, + this->connection_id = tnc->tnccs->create_connection(tnc->tnccs, + TNCCS_2_0, (tnccs_t*)this, _send_msg, &this->request_handshake_retry, NULL); if (!this->connection_id) { @@ -509,7 +564,7 @@ METHOD(tls_t, build, status_t, } /* Create PB-TNC Language Preference message */ - pref_lang = charon->imcs->get_preferred_language(charon->imcs); + pref_lang = tnc->imcs->get_preferred_language(tnc->imcs); msg = pb_language_preference_msg_create(chunk_create(pref_lang, strlen(pref_lang))); this->mutex->lock(this->mutex); @@ -517,12 +572,12 @@ METHOD(tls_t, build, status_t, this->batch->add_msg(this->batch, msg); this->mutex->unlock(this->mutex); - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_CREATE); - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + TNC_CONNECTION_STATE_CREATE); + tnc->imcs->notify_connection_change(tnc->imcs, this->connection_id, + TNC_CONNECTION_STATE_HANDSHAKE); this->send_msg = TRUE; - charon->imcs->begin_handshake(charon->imcs, this->connection_id); + tnc->imcs->begin_handshake(tnc->imcs, this->connection_id); this->send_msg = FALSE; } @@ -639,7 +694,7 @@ METHOD(tls_t, is_complete, bool, if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) { - return charon->imvs->enforce_recommendation(charon->imvs, rec, eval); + return tnc->imvs->enforce_recommendation(tnc->imvs, rec, eval); } else { @@ -656,8 +711,8 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_20_t *this) { - charon->tnccs->remove_connection(charon->tnccs, this->connection_id, - this->is_server); + tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, + this->is_server); this->state_machine->destroy(this->state_machine); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c index e6dc699e6..4f419ecf0 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c @@ -16,7 +16,7 @@ #include "tnccs_20_plugin.h" #include "tnccs_20.h" -#include <daemon.h> +#include <tnc/tnccs/tnccs_manager.h> METHOD(plugin_t, get_name, char*, tnccs_20_plugin_t *this) @@ -24,11 +24,23 @@ METHOD(plugin_t, get_name, char*, return "tnccs-20"; } +METHOD(plugin_t, get_features, int, + tnccs_20_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnccs_method_register, tnccs_20_create), + PLUGIN_PROVIDE(CUSTOM, "tnccs-2.0"), + PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), + PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), + PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, tnccs_20_plugin_t *this) { - charon->tnccs->remove_method(charon->tnccs, - (tnccs_constructor_t)tnccs_20_create); free(this); } @@ -42,14 +54,11 @@ plugin_t *tnccs_20_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_2_0, - (tnccs_constructor_t)tnccs_20_create); - return &this->plugin; } diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.am b/src/libcharon/plugins/tnccs_dynamic/Makefile.am index 9a81d065f..57c2baaf0 100644 --- a/src/libcharon/plugins/tnccs_dynamic/Makefile.am +++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.am @@ -1,6 +1,9 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @@ -8,7 +11,9 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la else plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la -libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libstrongswan_tnccs_dynamic_la_LIBADD = \ + $(top_builddir)/src/libtncif/libtncif.la \ + $(top_builddir)/src/libtnccs/libtnccs.la endif libstrongswan_tnccs_dynamic_la_SOURCES = \ diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.in b/src/libcharon/plugins/tnccs_dynamic/Makefile.in index dda1472db..ab24d32d3 100644 --- a/src/libcharon/plugins/tnccs_dynamic/Makefile.in +++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.in @@ -75,7 +75,8 @@ am__base_list = \ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) @MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_DEPENDENCIES = \ -@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la am_libstrongswan_tnccs_dynamic_la_OBJECTS = tnccs_dynamic_plugin.lo \ tnccs_dynamic.lo libstrongswan_tnccs_dynamic_la_OBJECTS = \ @@ -196,6 +197,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -204,6 +208,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -220,11 +225,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -268,6 +275,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ @@ -278,13 +286,19 @@ top_srcdir = @top_srcdir@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtnccs AM_CFLAGS = -rdynamic @MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la -@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_FALSE@libstrongswan_tnccs_dynamic_la_LIBADD = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtncif/libtncif.la \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtnccs/libtnccs.la + libstrongswan_tnccs_dynamic_la_SOURCES = \ tnccs_dynamic_plugin.h tnccs_dynamic_plugin.c tnccs_dynamic.h tnccs_dynamic.c diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c index b7985fa51..b68d2dd6b 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c @@ -15,8 +15,9 @@ #include "tnccs_dynamic.h" -#include <tnc/tnccs/tnccs.h> -#include <daemon.h> +#include <tnc/tnc.h> + +#include <debug.h> typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t; @@ -75,8 +76,7 @@ METHOD(tls_t, process, status_t, type = determine_tnccs_protocol(*(char*)buf); DBG1(DBG_TNC, "%N protocol detected dynamically", tnccs_type_names, type); - this->tls = (tls_t*)charon->tnccs->create_instance(charon->tnccs, - type, TRUE); + this->tls = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, type, TRUE); if (!this->tls) { DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type); diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c index 089a3ed57..6f581c543 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c @@ -16,7 +16,7 @@ #include "tnccs_dynamic_plugin.h" #include "tnccs_dynamic.h" -#include <daemon.h> +#include <tnc/tnccs/tnccs_manager.h> METHOD(plugin_t, get_name, char*, tnccs_dynamic_plugin_t *this) @@ -24,11 +24,24 @@ METHOD(plugin_t, get_name, char*, return "tnccs-dynamic"; } +METHOD(plugin_t, get_features, int, + tnccs_dynamic_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK(tnccs_method_register, tnccs_dynamic_create), + PLUGIN_PROVIDE(CUSTOM, "tnccs-dynamic"), + PLUGIN_DEPENDS(CUSTOM, "tnccs-1.1"), + PLUGIN_DEPENDS(CUSTOM, "tnccs-2.0"), + PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), + PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), + }; + *features = f; + return countof(f); +} + METHOD(plugin_t, destroy, void, tnccs_dynamic_plugin_t *this) { - charon->tnccs->remove_method(charon->tnccs, - (tnccs_constructor_t)tnccs_dynamic_create); free(this); } @@ -42,14 +55,11 @@ plugin_t *tnccs_dynamic_plugin_create() INIT(this, .plugin = { .get_name = _get_name, - .reload = (void*)return_false, + .get_features = _get_features, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_DYNAMIC, - (tnccs_constructor_t)tnccs_dynamic_create); - return &this->plugin; } diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index 013ceb7da..dd001e0bd 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -192,6 +192,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -200,6 +203,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -216,11 +220,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -264,6 +270,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index 4e43388ec..2f5e59b89 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -133,10 +133,8 @@ static u_int create_rekey(char *string) return 12 * 3600; } -/** - * Implementation of peer_enumerator_t.public.enumerate - */ -static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) +METHOD(enumerator_t, peer_enumerator_enumerate, bool, + peer_enumerator_t *this, peer_cfg_t **cfg) { char *name, *ike_proposal, *esp_proposal, *ike_rekey, *esp_rekey; char *local_id, *local_addr, *local_net; @@ -177,9 +175,9 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) name, 2, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO, 1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */ 1800, 900, /* jitter, overtime */ - TRUE, 60, /* mobike, dpddelay */ - NULL, NULL, /* vip, pool */ - FALSE, NULL, NULL); /* mediation, med by, peer id */ + TRUE, 60, /* mobike, dpddelay */ + NULL, NULL, /* vip, pool */ + FALSE, NULL, NULL); /* mediation, med by, peer id */ auth = auth_cfg_create(); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); auth->add(auth, AUTH_RULE_IDENTITY, @@ -208,32 +206,30 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) return FALSE; } -/** - * Implementation of peer_enumerator_t.public.destroy - */ -static void peer_enumerator_destroy(peer_enumerator_t *this) + +METHOD(enumerator_t, peer_enumerator_destroy, void, + peer_enumerator_t *this) { DESTROY_IF(this->peer_cfg); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(private_uci_config_t *this, - identification_t *me, - identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + private_uci_config_t *this, identification_t *me, identification_t *other) { - peer_enumerator_t *e = malloc_thing(peer_enumerator_t); - - e->public.enumerate = (void*)peer_enumerator_enumerate; - e->public.destroy = (void*)peer_enumerator_destroy; - e->peer_cfg = NULL; - e->inner = this->parser->create_section_enumerator(this->parser, + peer_enumerator_t *e; + + INIT(e, + .public = { + .enumerate = (void*)_peer_enumerator_enumerate, + .destroy = _peer_enumerator_destroy, + }, + .inner = this->parser->create_section_enumerator(this->parser, "local_id", "remote_id", "local_addr", "remote_addr", "local_net", "remote_net", "ike_proposal", "esp_proposal", - "ike_rekey", "esp_rekey", NULL); + "ike_rekey", "esp_rekey", NULL), + ); if (!e->inner) { free(e); @@ -254,10 +250,8 @@ typedef struct { enumerator_t *inner; } ike_enumerator_t; -/** - * Implementation of peer_enumerator_t.public.enumerate - */ -static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg) +METHOD(enumerator_t, ike_enumerator_enumerate, bool, + ike_enumerator_t *this, ike_cfg_t **cfg) { char *local_addr, *remote_addr, *ike_proposal; @@ -281,29 +275,27 @@ static bool ike_enumerator_enumerate(ike_enumerator_t *this, ike_cfg_t **cfg) return FALSE; } -/** - * Implementation of ike_enumerator_t.public.destroy - */ -static void ike_enumerator_destroy(ike_enumerator_t *this) +METHOD(enumerator_t, ike_enumerator_destroy, void, + ike_enumerator_t *this) { DESTROY_IF(this->ike_cfg); this->inner->destroy(this->inner); free(this); } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(private_uci_config_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + private_uci_config_t *this, host_t *me, host_t *other) { - ike_enumerator_t *e = malloc_thing(ike_enumerator_t); - - e->public.enumerate = (void*)ike_enumerator_enumerate; - e->public.destroy = (void*)ike_enumerator_destroy; - e->ike_cfg = NULL; - e->inner = this->parser->create_section_enumerator(this->parser, - "local_addr", "remote_addr", "ike_proposal", NULL); + ike_enumerator_t *e; + + INIT(e, + .public = { + .enumerate = (void*)_ike_enumerator_enumerate, + .destroy = _ike_enumerator_destroy, + }, + .inner = this->parser->create_section_enumerator(this->parser, + "local_addr", "remote_addr", "ike_proposal", NULL), + ); if (!e->inner) { free(e); @@ -312,10 +304,8 @@ static enumerator_t* create_ike_cfg_enumerator(private_uci_config_t *this, return &e->public; } -/** - * implements backend_t.get_peer_cfg_by_name. - */ -static peer_cfg_t *get_peer_cfg_by_name(private_uci_config_t *this, char *name) +METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, + private_uci_config_t *this, char *name) { enumerator_t *enumerator; peer_cfg_t *current, *found = NULL; @@ -336,10 +326,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_uci_config_t *this, char *name) return found; } -/** - * Implementation of uci_config_t.destroy. - */ -static void destroy(private_uci_config_t *this) +METHOD(uci_config_t, destroy, void, + private_uci_config_t *this) { free(this); } @@ -349,13 +337,19 @@ static void destroy(private_uci_config_t *this) */ uci_config_t *uci_config_create(uci_parser_t *parser) { - private_uci_config_t *this = malloc_thing(private_uci_config_t); - - this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator; - this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator; - this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name; - this->public.destroy = (void(*)(uci_config_t*))destroy; - this->parser = parser; + private_uci_config_t *this; + + INIT(this, + .public = { + .backend = { + .create_peer_cfg_enumerator = _create_peer_cfg_enumerator, + .create_ike_cfg_enumerator = _create_ike_cfg_enumerator, + .get_peer_cfg_by_name = _get_peer_cfg_by_name, + }, + .destroy = _destroy, + }, + .parser = parser, + ); return &this->public; } diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c index aee2505e3..af4a6a711 100644 --- a/src/libcharon/plugins/uci/uci_control.c +++ b/src/libcharon/plugins/uci/uci_control.c @@ -76,8 +76,7 @@ static void write_fifo(private_uci_control_t *this, char *format, ...) */ static void status(private_uci_control_t *this, char *name) { - enumerator_t *configs, *sas; - iterator_t *children; + enumerator_t *configs, *sas, *children; ike_sa_t *ike_sa; child_sa_t *child_sa; peer_cfg_t *peer_cfg; @@ -92,7 +91,8 @@ static void status(private_uci_control_t *this, char *name) { continue; } - sas = charon->controller->create_ike_sa_enumerator(charon->controller); + sas = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (sas->enumerate(sas, &ike_sa)) { if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg))) @@ -110,8 +110,8 @@ static void status(private_uci_control_t *this, char *name) fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa), ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa)); - children = ike_sa->create_child_sa_iterator(ike_sa); - while (children->iterate(children, (void**)&child_sa)) + children = ike_sa->create_child_sa_enumerator(ike_sa); + while (children->enumerate(children, (void**)&child_sa)) { fprintf(out, "%#R", child_sa->get_traffic_selectors(child_sa, FALSE)); @@ -148,8 +148,8 @@ static void initiate(private_uci_control_t *this, char *name) enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); if (enumerator->enumerate(enumerator, &child_cfg) && charon->controller->initiate(charon->controller, peer_cfg, - child_cfg->get_ref(child_cfg), - controller_cb_empty, NULL) == SUCCESS) + child_cfg->get_ref(child_cfg), + controller_cb_empty, NULL, 0) == SUCCESS) { write_fifo(this, "connection '%s' established\n", name); } @@ -174,7 +174,8 @@ static void terminate(private_uci_control_t *this, char *name) ike_sa_t *ike_sa; u_int id; - enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + enumerator = charon->controller->create_ike_sa_enumerator( + charon->controller, TRUE); while (enumerator->enumerate(enumerator, &ike_sa)) { if (streq(name, ike_sa->get_name(ike_sa))) @@ -182,7 +183,7 @@ static void terminate(private_uci_control_t *this, char *name) id = ike_sa->get_unique_id(ike_sa); enumerator->destroy(enumerator); charon->controller->terminate_ike(charon->controller, id, - controller_cb_empty, NULL); + controller_cb_empty, NULL, 0); write_fifo(this, "connection '%s' terminated\n", name); return; } @@ -265,10 +266,8 @@ static job_requeue_t receive(private_uci_control_t *this) return JOB_REQUEUE_FAIR; } -/** - * Implementation of uci_control_t.destroy - */ -static void destroy(private_uci_control_t *this) +METHOD(uci_control_t, destroy, void, + private_uci_control_t *this) { this->job->cancel(this->job); unlink(FIFO_FILE); @@ -280,9 +279,13 @@ static void destroy(private_uci_control_t *this) */ uci_control_t *uci_control_create() { - private_uci_control_t *this = malloc_thing(private_uci_control_t); + private_uci_control_t *this; - this->public.destroy = (void(*)(uci_control_t*))destroy; + INIT(this, + .public = { + .destroy = _destroy, + }, + ); unlink(FIFO_FILE); if (mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0) @@ -292,8 +295,8 @@ uci_control_t *uci_control_create() } else { - this->job = callback_job_create((callback_job_cb_t)receive, - this, NULL, NULL); + 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; diff --git a/src/libcharon/plugins/uci/uci_creds.c b/src/libcharon/plugins/uci/uci_creds.c index 4d664feb2..f5d5ace70 100644 --- a/src/libcharon/plugins/uci/uci_creds.c +++ b/src/libcharon/plugins/uci/uci_creds.c @@ -51,11 +51,9 @@ typedef struct { identification_t *other; } shared_enumerator_t; -/** - * Implementation of shared_enumerator_t.public.enumerate - */ -static bool shared_enumerator_enumerate(shared_enumerator_t *this, - shared_key_t **key, id_match_t *me, id_match_t *other) +METHOD(enumerator_t, shared_enumerator_enumerate, bool, + shared_enumerator_t *this, shared_key_t **key, id_match_t *me, + id_match_t *other) { char *local_id, *remote_id, *psk; identification_t *local, *remote; @@ -107,23 +105,17 @@ static bool shared_enumerator_enumerate(shared_enumerator_t *this, return TRUE; } -/** - * Implementation of shared_enumerator_t.public.destroy - */ -static void shared_enumerator_destroy(shared_enumerator_t *this) +METHOD(enumerator_t, shared_enumerator_destroy, void, + shared_enumerator_t *this) { this->inner->destroy(this->inner); DESTROY_IF(this->current); free(this); } -/** - * Implementation of backend_t.create_shared_cfg_enumerator. - */ -static enumerator_t* create_shared_enumerator(private_uci_creds_t *this, - shared_key_type_t type, - identification_t *me, - identification_t *other) +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_uci_creds_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) { shared_enumerator_t *e; @@ -132,14 +124,16 @@ static enumerator_t* create_shared_enumerator(private_uci_creds_t *this, return NULL; } - e = malloc_thing(shared_enumerator_t); - e->current = NULL; - e->public.enumerate = (void*)shared_enumerator_enumerate; - e->public.destroy = (void*)shared_enumerator_destroy; - e->me = me; - e->other = other; - e->inner = this->parser->create_section_enumerator(this->parser, - "local_id", "remote_id", "psk", NULL); + INIT(e, + .public = { + .enumerate = (void*)_shared_enumerator_enumerate, + .destroy = _shared_enumerator_destroy, + }, + .me = me, + .other = other, + .inner = this->parser->create_section_enumerator(this->parser, + "local_id", "remote_id", "psk", NULL), + ); if (!e->inner) { free(e); @@ -148,24 +142,28 @@ static enumerator_t* create_shared_enumerator(private_uci_creds_t *this, return &e->public; } -/** - * Implementation of uci_creds_t.destroy - */ -static void destroy(private_uci_creds_t *this) +METHOD(uci_creds_t, destroy, void, + private_uci_creds_t *this) { free(this); } uci_creds_t *uci_creds_create(uci_parser_t *parser) { - private_uci_creds_t *this = malloc_thing(private_uci_creds_t); - - this->public.credential_set.create_shared_enumerator = (enumerator_t*(*)(credential_set_t*, shared_key_type_t, identification_t*, identification_t*))create_shared_enumerator; - this->public.credential_set.create_private_enumerator = (enumerator_t*(*) (credential_set_t*, key_type_t, identification_t*))return_null; - this->public.credential_set.create_cert_enumerator = (enumerator_t*(*) (credential_set_t*, certificate_type_t, key_type_t,identification_t *, bool))return_null; - this->public.credential_set.create_cdp_enumerator = (enumerator_t*(*) (credential_set_t *,certificate_type_t, identification_t *))return_null; - this->public.credential_set.cache_cert = (void (*)(credential_set_t *, certificate_t *))nop; - this->public.destroy = (void(*) (uci_creds_t*))destroy; + private_uci_creds_t *this; + + INIT(this, + .public = { + .credential_set = { + .create_shared_enumerator = _create_shared_enumerator, + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + ); this->parser = parser; diff --git a/src/libcharon/plugins/uci/uci_parser.c b/src/libcharon/plugins/uci/uci_parser.c index 6de55d218..2429e9e44 100644 --- a/src/libcharon/plugins/uci/uci_parser.c +++ b/src/libcharon/plugins/uci/uci_parser.c @@ -57,10 +57,8 @@ typedef struct { char *keywords[]; } section_enumerator_t; -/** - * Implementation of section_enumerator_t.enumerate - */ -static bool section_enumerator_enumerate(section_enumerator_t *this, ...) +METHOD(enumerator_t, section_enumerator_enumerate, bool, + section_enumerator_t *this, ...) { struct uci_element *element; char **value; @@ -104,19 +102,15 @@ static bool section_enumerator_enumerate(section_enumerator_t *this, ...) return TRUE; } -/** - * Implementation of section_enumerator_t.public.destroy - */ -static void section_enumerator_destroy(section_enumerator_t *this) +METHOD(enumerator_t, section_enumerator_destroy, void, + section_enumerator_t *this) { uci_free_context(this->ctx); free(this); } -/** - * Implementation of backend_t.create_section_enumerator. - */ -static enumerator_t* create_section_enumerator(private_uci_parser_t *this, ...) +METHOD(uci_parser_t, create_section_enumerator, enumerator_t*, + private_uci_parser_t *this, ...) { section_enumerator_t *e; va_list args; @@ -140,8 +134,8 @@ static enumerator_t* create_section_enumerator(private_uci_parser_t *this, ...) while (e->keywords[i++]); va_end(args); - e->public.enumerate = (void*)section_enumerator_enumerate; - e->public.destroy = (void*)section_enumerator_destroy; + e->public.enumerate = (void*)_section_enumerator_enumerate; + e->public.destroy = _section_enumerator_destroy; /* load uci context */ e->ctx = uci_alloc_context(); @@ -160,10 +154,8 @@ static enumerator_t* create_section_enumerator(private_uci_parser_t *this, ...) return &e->public; } -/** - * Implementation of uci_parser_t.destroy. - */ -static void destroy(private_uci_parser_t *this) +METHOD(uci_parser_t, destroy, void, + private_uci_parser_t *this) { free(this->package); free(this); @@ -174,12 +166,15 @@ static void destroy(private_uci_parser_t *this) */ uci_parser_t *uci_parser_create(char *package) { - private_uci_parser_t *this = malloc_thing(private_uci_parser_t); - - this->public.create_section_enumerator = (enumerator_t*(*)(uci_parser_t*, ...))create_section_enumerator; - this->public.destroy = (void(*)(uci_parser_t*))destroy; - - this->package = strdup(package); + private_uci_parser_t *this; + + INIT(this, + .public = { + .create_section_enumerator = _create_section_enumerator, + .destroy = _destroy, + }, + .package = strdup(package), + ); return &this->public; } diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c index a6d24c32b..497c473a4 100644 --- a/src/libcharon/plugins/uci/uci_plugin.c +++ b/src/libcharon/plugins/uci/uci_plugin.c @@ -92,10 +92,10 @@ plugin_t *uci_plugin_create() }, }, .parser = uci_parser_create(UCI_PACKAGE), - .config = uci_config_create(this->parser), - .creds = uci_creds_create(this->parser), .control = uci_control_create(), ); + this->config = uci_config_create(this->parser); + this->creds = uci_creds_create(this->parser); charon->backends->add_backend(charon->backends, &this->config->backend); lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in index 2fee3da82..106c9b1fe 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.in +++ b/src/libcharon/plugins/unit_tester/Makefile.in @@ -198,6 +198,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -206,6 +209,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -222,11 +226,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -270,6 +276,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index 49cffe218..fb7b38f65 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -194,6 +194,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -202,6 +205,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -218,11 +222,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -266,6 +272,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c index 8e58b1a9b..2bd757ec7 100644 --- a/src/libcharon/plugins/updown/updown_listener.c +++ b/src/libcharon/plugins/updown/updown_listener.c @@ -115,37 +115,15 @@ METHOD(listener_t, child_updown, bool, while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) { char command[1024]; - char *my_client, *other_client, *my_client_mask, *other_client_mask; - char *pos, *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc; + host_t *my_client, *other_client; + u_int8_t my_client_mask, other_client_mask; + char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc; mark_t mark; bool is_host, is_ipv6; FILE *shell; - /* get subnet/bits from string */ - if (asprintf(&my_client, "%R", my_ts) < 0) - { - my_client = NULL; - } - pos = strchr(my_client, '/'); - *pos = '\0'; - my_client_mask = pos + 1; - pos = strchr(my_client_mask, '['); - if (pos) - { - *pos = '\0'; - } - if (asprintf(&other_client, "%R", other_ts) < 0) - { - other_client = NULL; - } - pos = strchr(other_client, '/'); - *pos = '\0'; - other_client_mask = pos + 1; - pos = strchr(other_client_mask, '['); - if (pos) - { - *pos = '\0'; - } + my_ts->to_subnet(my_ts, &my_client, &my_client_mask); + other_ts->to_subnet(other_ts, &other_client, &other_client_mask); if (vip) { @@ -248,16 +226,12 @@ METHOD(listener_t, child_updown, bool, "PLUTO_REQID='%u' " "PLUTO_ME='%H' " "PLUTO_MY_ID='%Y' " - "PLUTO_MY_CLIENT='%s/%s' " - "PLUTO_MY_CLIENT_NET='%s' " - "PLUTO_MY_CLIENT_MASK='%s' " + "PLUTO_MY_CLIENT='%H/%u' " "PLUTO_MY_PORT='%u' " "PLUTO_MY_PROTOCOL='%u' " "PLUTO_PEER='%H' " "PLUTO_PEER_ID='%Y' " - "PLUTO_PEER_CLIENT='%s/%s' " - "PLUTO_PEER_CLIENT_NET='%s' " - "PLUTO_PEER_CLIENT_MASK='%s' " + "PLUTO_PEER_CLIENT='%H/%u' " "PLUTO_PEER_PORT='%u' " "PLUTO_PEER_PROTOCOL='%u' " "%s" @@ -274,12 +248,10 @@ METHOD(listener_t, child_updown, bool, child_sa->get_reqid(child_sa), me, ike_sa->get_my_id(ike_sa), my_client, my_client_mask, - my_client, my_client_mask, my_ts->get_from_port(my_ts), my_ts->get_protocol(my_ts), other, ike_sa->get_other_id(ike_sa), other_client, other_client_mask, - other_client, other_client_mask, other_ts->get_from_port(other_ts), other_ts->get_protocol(other_ts), virtual_ip, @@ -288,8 +260,8 @@ METHOD(listener_t, child_updown, bool, udp_enc, config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "", script); - free(my_client); - free(other_client); + my_client->destroy(my_client); + other_client->destroy(other_client); free(virtual_ip); free(mark_in); free(mark_out); diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in index 37ae5f9c3..2534f4bec 100644 --- a/src/libcharon/plugins/whitelist/Makefile.in +++ b/src/libcharon/plugins/whitelist/Makefile.in @@ -202,6 +202,9 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +axis2c_CFLAGS = @axis2c_CFLAGS@ +axis2c_LIBS = @axis2c_LIBS@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -210,6 +213,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -226,11 +230,13 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ +imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -274,6 +280,7 @@ sharedstatedir = @sharedstatedir@ soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ +starter_plugins = @starter_plugins@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ systemdsystemunitdir = @systemdsystemunitdir@ diff --git a/src/libcharon/plugins/whitelist/whitelist_control.c b/src/libcharon/plugins/whitelist/whitelist_control.c index 4a1fc5d87..202c9a418 100644 --- a/src/libcharon/plugins/whitelist/whitelist_control.c +++ b/src/libcharon/plugins/whitelist/whitelist_control.c @@ -225,8 +225,8 @@ whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener) return NULL; } - this->job = callback_job_create((callback_job_cb_t)receive, - this, NULL, NULL); + 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; |