diff options
Diffstat (limited to 'src/libcharon/plugins/eap_radius')
-rw-r--r-- | src/libcharon/plugins/eap_radius/Makefile.am | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/Makefile.in | 82 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius.c | 116 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius.h | 22 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_accounting.c | 30 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_dae.c | 18 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_forward.c | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_plugin.c | 79 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_provider.c | 118 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_provider.h | 8 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_xauth.c | 202 | ||||
-rw-r--r-- | src/libcharon/plugins/eap_radius/eap_radius_xauth.h | 49 |
12 files changed, 580 insertions, 159 deletions
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index 628adbeb3..6fdb0d099 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -1,8 +1,11 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libradius -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libradius - -AM_CFLAGS = -rdynamic +AM_CFLAGS = \ + -rdynamic if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-eap-radius.la @@ -14,6 +17,7 @@ endif libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ + eap_radius_xauth.h eap_radius_xauth.c \ eap_radius_accounting.h eap_radius_accounting.c \ eap_radius_provider.h eap_radius_provider.c \ eap_radius_dae.h eap_radius_dae.c \ diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index aa2cf3da5..24818d4fb 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -62,7 +62,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.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 + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -101,11 +101,14 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) @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 eap_radius_accounting.lo eap_radius_provider.lo \ - eap_radius_dae.lo eap_radius_forward.lo + eap_radius.lo eap_radius_xauth.lo eap_radius_accounting.lo \ + eap_radius_provider.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 \ +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +libstrongswan_eap_radius_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_eap_radius_la_LDFLAGS) \ $(LDFLAGS) -o $@ @@ -118,13 +121,26 @@ 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) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libstrongswan_eap_radius_la_SOURCES) DIST_SOURCES = $(libstrongswan_eap_radius_la_SOURCES) am__can_run_installinfo = \ @@ -138,6 +154,7 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -150,6 +167,8 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CHECK_CFLAGS = @CHECK_CFLAGS@ CHECK_LIBS = @CHECK_LIBS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -165,6 +184,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +GENHTML = @GENHTML@ GPERF = @GPERF@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ @@ -173,6 +193,7 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ @@ -219,6 +240,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKLIB = @SOCKLIB@ STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -247,6 +269,7 @@ charon_natt_port = @charon_natt_port@ charon_plugins = @charon_plugins@ charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ @@ -324,16 +347,22 @@ 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_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libradius + +AM_CFLAGS = \ + -rdynamic -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 \ + eap_radius_xauth.h eap_radius_xauth.c \ eap_radius_accounting.h eap_radius_accounting.c \ eap_radius_provider.h eap_radius_provider.c \ eap_radius_dae.h eap_radius_dae.c \ @@ -416,7 +445,7 @@ clean-pluginLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libstrongswan-eap-radius.la: $(libstrongswan_eap_radius_la_OBJECTS) $(libstrongswan_eap_radius_la_DEPENDENCIES) $(EXTRA_libstrongswan_eap_radius_la_DEPENDENCIES) - $(libstrongswan_eap_radius_la_LINK) $(am_libstrongswan_eap_radius_la_rpath) $(libstrongswan_eap_radius_la_OBJECTS) $(libstrongswan_eap_radius_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(libstrongswan_eap_radius_la_LINK) $(am_libstrongswan_eap_radius_la_rpath) $(libstrongswan_eap_radius_la_OBJECTS) $(libstrongswan_eap_radius_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -430,27 +459,28 @@ distclean-compile: @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)/eap_radius_provider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_xauth.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@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(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@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(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@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index c9e1cdaad..b06b6c392 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -75,21 +75,6 @@ struct private_eap_radius_t { * Prefix to prepend to EAP identity */ char *id_prefix; - - /** - * Handle the Class attribute as group membership information? - */ - bool class_group; - - /** - * Handle the Filter-Id attribute as IPsec CHILD_SA name? - */ - bool filter_id; - - /** - * Format string we use for Called/Calling-Station-Id for a host - */ - char *station_id_fmt; }; /** @@ -163,21 +148,16 @@ static bool radius2ike(private_eap_radius_t *this, } /** - * Add a set of RADIUS attributes to a request message + * See header. */ -static void add_radius_request_attrs(private_eap_radius_t *this, - radius_message_t *request) +void eap_radius_build_attributes(radius_message_t *request) { ike_sa_t *ike_sa; host_t *host; - char buf[40]; + char buf[40], *station_id_fmt;; u_int32_t value; chunk_t chunk; - chunk = chunk_from_str(this->id_prefix); - chunk = chunk_cata("cc", chunk, this->peer->get_encoding(this->peer)); - request->add(request, RAT_USER_NAME, chunk); - /* virtual NAS-Port-Type */ value = htonl(5); request->add(request, RAT_NAS_PORT_TYPE, chunk_from_thing(value)); @@ -205,13 +185,37 @@ static void add_radius_request_attrs(private_eap_radius_t *this, default: break; } - snprintf(buf, sizeof(buf), this->station_id_fmt, host); + if (lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.station_id_with_port", + TRUE, charon->name)) + { + station_id_fmt = "%#H"; + } + else + { + station_id_fmt = "%H"; + } + snprintf(buf, sizeof(buf), station_id_fmt, host); request->add(request, RAT_CALLED_STATION_ID, chunk_from_str(buf)); host = ike_sa->get_other_host(ike_sa); - snprintf(buf, sizeof(buf), this->station_id_fmt, host); + snprintf(buf, sizeof(buf), station_id_fmt, host); request->add(request, RAT_CALLING_STATION_ID, chunk_from_str(buf)); } +} + +/** + * Add a set of RADIUS attributes to a request message + */ +static void add_radius_request_attrs(private_eap_radius_t *this, + radius_message_t *request) +{ + chunk_t chunk; + chunk = chunk_from_str(this->id_prefix); + chunk = chunk_cata("cc", chunk, this->peer->get_encoding(this->peer)); + request->add(request, RAT_USER_NAME, chunk); + + eap_radius_build_attributes(request); eap_radius_forward_from_ike(request); } @@ -268,7 +272,7 @@ METHOD(eap_method_t, initiate, status_t, /** * Handle the Class attribute as group membership information */ -static void process_class(private_eap_radius_t *this, radius_message_t *msg) +static void process_class(radius_message_t *msg) { enumerator_t *enumerator; chunk_t data; @@ -305,7 +309,7 @@ static void process_class(private_eap_radius_t *this, radius_message_t *msg) /** * Handle the Filter-Id attribute as IPsec CHILD_SA name */ -static void process_filter_id(private_eap_radius_t *this, radius_message_t *msg) +static void process_filter_id(radius_message_t *msg) { enumerator_t *enumerator; int type; @@ -361,7 +365,7 @@ static void process_filter_id(private_eap_radius_t *this, radius_message_t *msg) /** * Handle Session-Timeout attribte and Interim updates */ -static void process_timeout(private_eap_radius_t *this, radius_message_t *msg) +static void process_timeout(radius_message_t *msg) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -390,8 +394,7 @@ static void process_timeout(private_eap_radius_t *this, radius_message_t *msg) /** * Handle Framed-IP-Address and other IKE configuration attributes */ -static void process_cfg_attributes(private_eap_radius_t *this, - radius_message_t *msg) +static void process_cfg_attributes(radius_message_t *msg) { eap_radius_provider_t *provider; enumerator_t *enumerator; @@ -412,7 +415,8 @@ static void process_cfg_attributes(private_eap_radius_t *this, host = host_create_from_chunk(AF_INET, data, 0); if (host) { - provider->add_framed_ip(provider, this->peer, host); + provider->add_framed_ip(provider, + ike_sa->get_unique_id(ike_sa), host); } } } @@ -429,8 +433,9 @@ static void process_cfg_attributes(private_eap_radius_t *this, case 36: /* CVPN3000-IPSec-Banner2 */ if (ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) { - provider->add_attribute(provider, this->peer, - UNITY_BANNER, data); + provider->add_attribute(provider, + ike_sa->get_unique_id(ike_sa), + UNITY_BANNER, data); } break; default: @@ -442,6 +447,25 @@ static void process_cfg_attributes(private_eap_radius_t *this, } } +/** + * See header. + */ +void eap_radius_process_attributes(radius_message_t *message) +{ + if (lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.class_group", FALSE, charon->name)) + { + process_class(message); + } + if (lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.filter_id", FALSE, charon->name)) + { + process_filter_id(message); + } + process_timeout(message); + process_cfg_attributes(message); +} + METHOD(eap_method_t, process, status_t, private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out) { @@ -479,16 +503,7 @@ METHOD(eap_method_t, process, status_t, status = FAILED; break; case RMC_ACCESS_ACCEPT: - if (this->class_group) - { - process_class(this, response); - } - if (this->filter_id) - { - process_filter_id(this, response); - } - process_timeout(this, response); - process_cfg_attributes(this, response); + eap_radius_process_attributes(response); DBG1(DBG_IKE, "RADIUS authentication of '%Y' successful", this->peer); status = SUCCESS; @@ -589,22 +604,7 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer .id_prefix = lib->settings->get_str(lib->settings, "%s.plugins.eap-radius.id_prefix", "", charon->name), - .class_group = lib->settings->get_bool(lib->settings, - "%s.plugins.eap-radius.class_group", FALSE, - charon->name), - .filter_id = lib->settings->get_bool(lib->settings, - "%s.plugins.eap-radius.filter_id", FALSE, - charon->name), ); - if (lib->settings->get_bool(lib->settings, - "%s.plugins.eap-radius.station_id_with_port", TRUE, charon->name)) - { - this->station_id_fmt = "%#H"; - } - else - { - this->station_id_fmt = "%H"; - } this->client = eap_radius_create_client(); if (!this->client) { diff --git a/src/libcharon/plugins/eap_radius/eap_radius.h b/src/libcharon/plugins/eap_radius/eap_radius.h index 875543554..ce583ac44 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.h +++ b/src/libcharon/plugins/eap_radius/eap_radius.h @@ -24,6 +24,7 @@ typedef struct eap_radius_t eap_radius_t; #include <sa/eap/eap_method.h> +#include <radius_message.h> /** * Implementation of the eap_method_t interface using a RADIUS server. @@ -45,4 +46,25 @@ struct eap_radius_t { */ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer); +/** + * Process additional attributes from an Access-Accept. + * + * Parses and applies additional authorization attributes from an Accept + * message, such as group membership information or IKE configuration + * attributes. + * + * @param message Access-Accept message to process + */ +void eap_radius_process_attributes(radius_message_t *message); + +/** + * Build additional attributes for an Access-Request. + * + * Adds additional RADIUS attributes to use with Access-Request, such as + * different NAS specific attributes. + * + * @param message Access-Request message to add attributes to + */ +void eap_radius_build_attributes(radius_message_t *message); + #endif /** EAP_RADIUS_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c index e9843470a..e004589da 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c @@ -56,6 +56,11 @@ struct private_eap_radius_accounting_t { * Format string we use for Called/Calling-Station-Id for a host */ char *station_id_fmt; + + /** + * Disable accounting unless IKE_SA has at least one virtual IP + */ + bool acct_req_vip; }; /** @@ -438,6 +443,22 @@ static void schedule_interim(private_eap_radius_accounting_t *this, } /** + * Check if an IKE_SA has assigned a virtual IP (to peer) + */ +static bool has_vip(ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + host_t *host; + bool found; + + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); + found = enumerator->enumerate(enumerator, &host); + enumerator->destroy(enumerator); + + return found; +} + +/** * Send an accounting start message */ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa) @@ -446,6 +467,11 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa) entry_t *entry; u_int32_t value; + if (this->acct_req_vip && !has_vip(ike_sa)) + { + return; + } + this->mutex->lock(this->mutex); entry = get_or_create_entry(this, ike_sa); @@ -700,6 +726,10 @@ eap_radius_accounting_t *eap_radius_accounting_create() singleton = this; charon->bus->add_listener(charon->bus, &this->public.listener); } + this->acct_req_vip = lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.accounting_requires_vip", + FALSE, charon->name); + return &this->public; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_dae.c b/src/libcharon/plugins/eap_radius/eap_radius_dae.c index 2ea2b059c..f22ddc56f 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_dae.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_dae.c @@ -379,21 +379,17 @@ static void process_coa(private_eap_radius_dae_t *this, /** * Receive RADIUS DAE requests */ -static job_requeue_t receive(private_eap_radius_dae_t *this) +static bool 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, + len = recvfrom(this->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len); - thread_cancelability(oldstate); - if (len > 0) { request = radius_message_parse(chunk_create(buf, len)); @@ -433,11 +429,11 @@ static job_requeue_t receive(private_eap_radius_dae_t *this) DBG1(DBG_NET, "ignoring invalid RADIUS DAE request"); } } - else + else if (errno != EWOULDBLOCK) { DBG1(DBG_NET, "receiving RADIUS DAE request failed: %s", strerror(errno)); } - return JOB_REQUEUE_DIRECT; + return TRUE; } /** @@ -483,6 +479,7 @@ METHOD(eap_radius_dae_t, destroy, void, { if (this->fd != -1) { + lib->watcher->remove(lib->watcher, this->fd); close(this->fd); } DESTROY_IF(this->signer); @@ -533,9 +530,8 @@ eap_radius_dae_t *eap_radius_dae_create(eap_radius_accounting_t *accounting) return NULL; } - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, - this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); + lib->watcher->add(lib->watcher, this->fd, WATCHER_READ, + (watcher_cb_t)receive, this); return &this->public; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.c b/src/libcharon/plugins/eap_radius/eap_radius_forward.c index e9124877c..3e80e8918 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_forward.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.c @@ -248,7 +248,8 @@ static void ike2queue(message_t *message, linked_list_t *queue, enumerator = message->create_payload_enumerator(message); while (enumerator->enumerate(enumerator, &payload)) { - if (payload->get_type(payload) == NOTIFY) + if (payload->get_type(payload) == NOTIFY || + payload->get_type(payload) == NOTIFY_V1) { notify = (notify_payload_t*)payload; if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE) diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index e186cb0fe..90a4ef6de 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2009 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -16,6 +17,7 @@ #include "eap_radius_plugin.h" #include "eap_radius.h" +#include "eap_radius_xauth.h" #include "eap_radius_accounting.h" #include "eap_radius_dae.h" #include "eap_radius_forward.h" @@ -186,12 +188,60 @@ METHOD(plugin_t, get_name, char*, return "eap-radius"; } +/** + * Register listener + */ +static bool plugin_cb(private_eap_radius_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + this->accounting = eap_radius_accounting_create(); + this->forward = eap_radius_forward_create(); + this->provider = eap_radius_provider_create(); + + load_configs(this); + + if (lib->settings->get_bool(lib->settings, + "%s.plugins.eap-radius.dae.enable", FALSE, charon->name)) + { + this->dae = eap_radius_dae_create(this->accounting); + } + if (this->forward) + { + charon->bus->add_listener(charon->bus, &this->forward->listener); + } + hydra->attributes->add_provider(hydra->attributes, + &this->provider->provider); + } + else + { + hydra->attributes->remove_provider(hydra->attributes, + &this->provider->provider); + if (this->forward) + { + charon->bus->remove_listener(charon->bus, &this->forward->listener); + this->forward->destroy(this->forward); + } + DESTROY_IF(this->dae); + this->provider->destroy(this->provider); + this->accounting->destroy(this->accounting); + } + return TRUE; +} + METHOD(plugin_t, get_features, int, - eap_radius_plugin_t *this, plugin_feature_t *features[]) + private_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(CUSTOM, "eap-radius"), + PLUGIN_CALLBACK(xauth_method_register, eap_radius_xauth_create_server), + PLUGIN_PROVIDE(XAUTH_SERVER, "radius"), + PLUGIN_DEPENDS(CUSTOM, "eap-radius"), + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "eap-radius"), PLUGIN_DEPENDS(HASHER, HASH_MD5), PLUGIN_DEPENDS(SIGNER, AUTH_HMAC_MD5_128), PLUGIN_DEPENDS(RNG, RNG_WEAK), @@ -215,19 +265,9 @@ METHOD(plugin_t, reload, bool, METHOD(plugin_t, destroy, void, private_eap_radius_plugin_t *this) { - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); - this->provider->destroy(this->provider); - 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); - this->accounting->destroy(this->accounting); free(this); instance = NULL; } @@ -250,26 +290,9 @@ plugin_t *eap_radius_plugin_create() }, .configs = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - .accounting = eap_radius_accounting_create(), - .forward = eap_radius_forward_create(), - .provider = eap_radius_provider_create(), ); - - load_configs(this); instance = this; - if (lib->settings->get_bool(lib->settings, - "%s.plugins.eap-radius.dae.enable", FALSE, charon->name)) - { - this->dae = eap_radius_dae_create(this->accounting); - } - if (this->forward) - { - charon->bus->add_listener(charon->bus, &this->forward->listener); - } - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); - return &this->public.plugin; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_provider.c b/src/libcharon/plugins/eap_radius/eap_radius_provider.c index 6087313b5..7c794616b 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_provider.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_provider.c @@ -92,8 +92,8 @@ static void destroy_attr(attr_t *this) * Hashtable entry with leases and attributes */ typedef struct { - /** identity we assigned the IP lease */ - identification_t *id; + /** IKE_SA uniqe id we assign the IP lease */ + uintptr_t id; /** list of IP leases received from AAA, as host_t */ linked_list_t *addrs; /** list of configuration attributes, as attr_t */ @@ -105,7 +105,6 @@ typedef struct { */ static void destroy_entry(entry_t *this) { - this->id->destroy(this->id); this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy)); this->attrs->destroy_function(this->attrs, (void*)destroy_attr); free(this); @@ -114,19 +113,19 @@ static void destroy_entry(entry_t *this) /** * Get or create an entry from a locked hashtable */ -static entry_t* get_or_create_entry(hashtable_t *hashtable, identification_t *id) +static entry_t* get_or_create_entry(hashtable_t *hashtable, uintptr_t id) { entry_t *entry; - entry = hashtable->get(hashtable, id); + entry = hashtable->get(hashtable, (void*)id); if (!entry) { INIT(entry, - .id = id->clone(id), + .id = id, .addrs = linked_list_create(), .attrs = linked_list_create(), ); - hashtable->put(hashtable, entry->id, entry); + hashtable->put(hashtable, (void*)id, entry); } return entry; } @@ -139,7 +138,7 @@ static void put_or_destroy_entry(hashtable_t *hashtable, entry_t *entry) if (entry->addrs->get_count(entry->addrs) > 0 || entry->attrs->get_count(entry->attrs) > 0) { - hashtable->put(hashtable, entry->id, entry); + hashtable->put(hashtable, (void*)entry->id, entry); } else { @@ -150,24 +149,24 @@ static void put_or_destroy_entry(hashtable_t *hashtable, entry_t *entry) /** * Hashtable hash function */ -static u_int hash(identification_t *id) +static u_int hash(uintptr_t id) { - return chunk_hash_inc(id->get_encoding(id), id->get_type(id)); + return id; } /** * Hashtable equals function */ -static bool equals(identification_t *a, identification_t *b) +static bool equals(uintptr_t a, uintptr_t b) { - return a->equals(a, b); + return a == b; } /** * Insert an address entry to a locked claimed/unclaimed hashtable */ static void add_addr(private_eap_radius_provider_t *this, - hashtable_t *hashtable, identification_t *id, host_t *host) + hashtable_t *hashtable, uintptr_t id, host_t *host) { entry_t *entry; @@ -179,12 +178,12 @@ static void add_addr(private_eap_radius_provider_t *this, * Remove the next address from the locked hashtable stored for given id */ static host_t* remove_addr(private_eap_radius_provider_t *this, - hashtable_t *hashtable, identification_t *id) + hashtable_t *hashtable, uintptr_t id) { entry_t *entry; host_t *addr = NULL; - entry = hashtable->remove(hashtable, id); + entry = hashtable->remove(hashtable, (void*)id); if (entry) { entry->addrs->remove_first(entry->addrs, (void**)&addr); @@ -197,7 +196,7 @@ static host_t* remove_addr(private_eap_radius_provider_t *this, * Insert an attribute entry to a locked claimed/unclaimed hashtable */ static void add_attr(private_eap_radius_provider_t *this, - hashtable_t *hashtable, identification_t *id, attr_t *attr) + hashtable_t *hashtable, uintptr_t id, attr_t *attr) { entry_t *entry; @@ -209,12 +208,12 @@ static void add_attr(private_eap_radius_provider_t *this, * Remove the next attribute from the locked hashtable stored for given id */ static attr_t* remove_attr(private_eap_radius_provider_t *this, - hashtable_t *hashtable, identification_t *id) + hashtable_t *hashtable, uintptr_t id) { entry_t *entry; attr_t *attr = NULL; - entry = hashtable->remove(hashtable, id); + entry = hashtable->remove(hashtable, (void*)id); if (entry) { entry->attrs->remove_first(entry->attrs, (void**)&attr); @@ -228,12 +227,12 @@ static attr_t* remove_attr(private_eap_radius_provider_t *this, */ static void release_unclaimed(private_listener_t *this, ike_sa_t *ike_sa) { - identification_t *id; + uintptr_t id; entry_t *entry; - id = ike_sa->get_other_eap_id(ike_sa); + id = ike_sa->get_unique_id(ike_sa); this->mutex->lock(this->mutex); - entry = this->unclaimed->remove(this->unclaimed, id); + entry = this->unclaimed->remove(this->unclaimed, (void*)id); this->mutex->unlock(this->mutex); if (entry) { @@ -273,24 +272,70 @@ METHOD(listener_t, ike_updown, bool, return TRUE; } +/** + * Migrate an entry in hashtable from old to new id + */ +static void migrate_entry(hashtable_t *table, uintptr_t old, uintptr_t new) +{ + entry_t *entry; + + entry = table->remove(table, (void*)old); + if (entry) + { + entry->id = new; + entry = table->put(table, (void*)new, entry); + if (entry) + { /* shouldn't happen */ + destroy_entry(entry); + } + } +} + +METHOD(listener_t, ike_rekey, bool, + private_listener_t *this, ike_sa_t *old, ike_sa_t *new) +{ + uintptr_t old_id, new_id; + + old_id = old->get_unique_id(old); + new_id = new->get_unique_id(new); + + this->mutex->lock(this->mutex); + + migrate_entry(this->unclaimed, old_id, new_id); + migrate_entry(this->claimed, old_id, new_id); + + this->mutex->unlock(this->mutex); + + return TRUE; +} + METHOD(attribute_provider_t, acquire_address, host_t*, private_eap_radius_provider_t *this, linked_list_t *pools, identification_t *id, host_t *requested) { enumerator_t *enumerator; host_t *addr = NULL; + ike_sa_t *ike_sa; + uintptr_t sa; char *name; + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return NULL; + } + sa = ike_sa->get_unique_id(ike_sa); + enumerator = pools->create_enumerator(pools); while (enumerator->enumerate(enumerator, &name)) { if (streq(name, "radius")) { this->listener.mutex->lock(this->listener.mutex); - addr = remove_addr(this, this->listener.unclaimed, id); + addr = remove_addr(this, this->listener.unclaimed, sa); if (addr) { - add_addr(this, this->listener.claimed, id, addr->clone(addr)); + add_addr(this, this->listener.claimed, sa, addr->clone(addr)); } this->listener.mutex->unlock(this->listener.mutex); break; @@ -307,15 +352,24 @@ METHOD(attribute_provider_t, release_address, bool, { enumerator_t *enumerator; host_t *found = NULL; + ike_sa_t *ike_sa; + uintptr_t sa; char *name; + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return FALSE; + } + sa = ike_sa->get_unique_id(ike_sa); + enumerator = pools->create_enumerator(pools); while (enumerator->enumerate(enumerator, &name)) { if (streq(name, "radius")) { this->listener.mutex->lock(this->listener.mutex); - found = remove_addr(this, this->listener.claimed, id); + found = remove_addr(this, this->listener.claimed, sa); this->listener.mutex->unlock(this->listener.mutex); break; } @@ -378,6 +432,15 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, { attribute_enumerator_t *enumerator; attr_t *attr; + ike_sa_t *ike_sa; + uintptr_t sa; + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + return NULL; + } + sa = ike_sa->get_unique_id(ike_sa); INIT(enumerator, .public = { @@ -391,7 +454,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, this->listener.mutex->lock(this->listener.mutex); while (TRUE) { - attr = remove_attr(this, this->listener.unclaimed, id); + attr = remove_attr(this, this->listener.unclaimed, sa); if (!attr) { break; @@ -404,7 +467,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, } METHOD(eap_radius_provider_t, add_framed_ip, void, - private_eap_radius_provider_t *this, identification_t *id, host_t *ip) + private_eap_radius_provider_t *this, u_int32_t id, host_t *ip) { this->listener.mutex->lock(this->listener.mutex); add_addr(this, this->listener.unclaimed, id, ip); @@ -412,7 +475,7 @@ METHOD(eap_radius_provider_t, add_framed_ip, void, } METHOD(eap_radius_provider_t, add_attribute, void, - private_eap_radius_provider_t *this, identification_t *id, + private_eap_radius_provider_t *this, u_int32_t id, configuration_attribute_type_t type, chunk_t data) { attr_t *attr; @@ -460,6 +523,7 @@ eap_radius_provider_t *eap_radius_provider_create() .listener = { .public = { .ike_updown = _ike_updown, + .ike_rekey = _ike_rekey, .message = _message_hook, }, .claimed = hashtable_create((hashtable_hash_t)hash, diff --git a/src/libcharon/plugins/eap_radius/eap_radius_provider.h b/src/libcharon/plugins/eap_radius/eap_radius_provider.h index a0b4a6b62..5a62f4a38 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_provider.h +++ b/src/libcharon/plugins/eap_radius/eap_radius_provider.h @@ -39,20 +39,20 @@ struct eap_radius_provider_t { /** * Add a received Framed-IP-Address to the provider to serve to client. * - * @param id client identity + * @param id IKE_SA unique identifier * @param ip IP address received from RADIUS server, gets owned */ - void (*add_framed_ip)(eap_radius_provider_t *this, identification_t *id, + void (*add_framed_ip)(eap_radius_provider_t *this, u_int32_t id, host_t *ip); /** * Add a configuration attribute received from RADIUS to forward. * - * @param id client identity + * @param id IKE_SA unique identifier * @param type attribute type * @param data attribute data */ - void (*add_attribute)(eap_radius_provider_t *this, identification_t *id, + void (*add_attribute)(eap_radius_provider_t *this, u_int32_t id, configuration_attribute_type_t type, chunk_t data); /** diff --git a/src/libcharon/plugins/eap_radius/eap_radius_xauth.c b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c new file mode 100644 index 000000000..bd960d2bc --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 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_xauth.h" +#include "eap_radius_plugin.h" +#include "eap_radius.h" +#include "eap_radius_forward.h" + +#include <daemon.h> +#include <radius_client.h> + + +typedef struct private_eap_radius_xauth_t private_eap_radius_xauth_t; + +/** + * Private data of an eap_radius_xauth_t object. + */ +struct private_eap_radius_xauth_t { + + /** + * Public interface. + */ + eap_radius_xauth_t public; + + /** + * ID of the server + */ + identification_t *server; + + /** + * ID of the peer + */ + identification_t *peer; + + /** + * RADIUS connection + */ + radius_client_t *client; +}; + +METHOD(xauth_method_t, initiate, status_t, + private_eap_radius_xauth_t *this, cp_payload_t **out) +{ + cp_payload_t *cp; + + cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST); + cp->add_attribute(cp, configuration_attribute_create_chunk( + CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty)); + cp->add_attribute(cp, configuration_attribute_create_chunk( + CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty)); + *out = cp; + return NEED_MORE; +} + +/** + * Verify a password using RADIUS User-Name/User-Password attributes + */ +static status_t verify_radius(private_eap_radius_xauth_t *this, chunk_t pass) +{ + radius_message_t *request, *response; + status_t status = FAILED; + + request = radius_message_create(RMC_ACCESS_REQUEST); + request->add(request, RAT_USER_NAME, this->peer->get_encoding(this->peer)); + request->add(request, RAT_USER_PASSWORD, pass); + + eap_radius_build_attributes(request); + 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_ACCEPT: + eap_radius_process_attributes(response); + status = SUCCESS; + break; + case RMC_ACCESS_CHALLENGE: + DBG1(DBG_IKE, "RADIUS Access-Challenge not supported"); + /* FALL */ + case RMC_ACCESS_REJECT: + default: + DBG1(DBG_IKE, "RADIUS authentication of '%Y' failed", + this->peer); + break; + } + response->destroy(response); + } + else + { + eap_radius_handle_timeout(NULL); + } + request->destroy(request); + return status; +} + +METHOD(xauth_method_t, process, status_t, + private_eap_radius_xauth_t *this, cp_payload_t *in, cp_payload_t **out) +{ + configuration_attribute_t *attr; + enumerator_t *enumerator; + identification_t *id; + chunk_t user = chunk_empty, pass = chunk_empty; + + enumerator = in->create_attribute_enumerator(in); + while (enumerator->enumerate(enumerator, &attr)) + { + switch (attr->get_type(attr)) + { + case XAUTH_USER_NAME: + user = attr->get_chunk(attr); + break; + case XAUTH_USER_PASSWORD: + pass = attr->get_chunk(attr); + /* trim password to any null termination. As User-Password + * uses null padding, we can't have any null in it, and some + * clients actually send null terminated strings (Android). */ + pass.len = strnlen(pass.ptr, pass.len); + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (!user.ptr || !pass.ptr) + { + DBG1(DBG_IKE, "peer did not respond to our XAuth request"); + return FAILED; + } + if (user.len) + { + id = identification_create_from_data(user); + if (!id) + { + DBG1(DBG_IKE, "failed to parse provided XAuth username"); + return FAILED; + } + this->peer->destroy(this->peer); + this->peer = id; + } + return verify_radius(this, pass); +} + +METHOD(xauth_method_t, get_identity, identification_t*, + private_eap_radius_xauth_t *this) +{ + return this->peer; +} + +METHOD(xauth_method_t, destroy, void, + private_eap_radius_xauth_t *this) +{ + DESTROY_IF(this->client); + this->server->destroy(this->server); + this->peer->destroy(this->peer); + free(this); +} + +/* + * Described in header. + */ +eap_radius_xauth_t *eap_radius_xauth_create_server(identification_t *server, + identification_t *peer) +{ + private_eap_radius_xauth_t *this; + + INIT(this, + .public = { + .xauth_method = { + .initiate = _initiate, + .process = _process, + .get_identity = _get_identity, + .destroy = _destroy, + }, + }, + .server = server->clone(server), + .peer = peer->clone(peer), + .client = eap_radius_create_client(), + ); + + if (!this->client) + { + destroy(this); + return NULL; + } + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/eap_radius_xauth.h b/src/libcharon/plugins/eap_radius/eap_radius_xauth.h new file mode 100644 index 000000000..8571bbc9f --- /dev/null +++ b/src/libcharon/plugins/eap_radius/eap_radius_xauth.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 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_xauth eap_radius_xauth + * @{ @ingroup eap_radius + */ + +#ifndef EAP_RADIUS_XAUTH_H_ +#define EAP_RADIUS_XAUTH_H_ + +#include <sa/xauth/xauth_method.h> + +typedef struct eap_radius_xauth_t eap_radius_xauth_t; + +/** + * XAuth backend using plain RADIUS authentication (no EAP involved). + */ +struct eap_radius_xauth_t { + + /** + * Implements XAuth module interface + */ + xauth_method_t xauth_method; +}; + +/** + * Creates the RADIUS XAuth method, acting as server. + * + * @param server ID of the XAuth server + * @param peer ID of the XAuth client + * @return xauth_generic_t object + */ +eap_radius_xauth_t *eap_radius_xauth_create_server(identification_t *server, + identification_t *peer); + +#endif /** EAP_RADIUS_XAUTH_H_ @}*/ |