diff options
Diffstat (limited to 'src/charon')
-rw-r--r-- | src/charon/Makefile.am | 7 | ||||
-rw-r--r-- | src/charon/Makefile.in | 104 | ||||
-rw-r--r-- | src/charon/control/interface_manager.c | 15 | ||||
-rwxr-xr-x | src/charon/control/interfaces/stroke_interface.c | 21 | ||||
-rw-r--r-- | src/charon/encoding/payloads/eap_payload.c | 8 | ||||
-rw-r--r-- | src/charon/encoding/payloads/eap_payload.h | 11 | ||||
-rw-r--r-- | src/charon/encoding/payloads/id_payload.c | 3 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_sim.c | 482 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/eap_sim.h | 89 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/sim/eap_sim_file.c | 288 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap_authenticator.c | 15 | ||||
-rw-r--r-- | src/charon/sa/connect_manager.c | 223 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 9 | ||||
-rw-r--r-- | src/charon/sa/ike_sa_manager.c | 23 | ||||
-rw-r--r-- | src/charon/sa/ike_sa_manager.h | 21 |
15 files changed, 952 insertions, 367 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 9111191b6..1d7022336 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -104,7 +104,8 @@ endif INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \ - -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" + -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" \ + -DSIM_READER_LIB=\"${simreader}\" charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lgmp -lpthread -lm -ldl if USE_LIBCURL @@ -126,6 +127,10 @@ if USE_EAP_SIM eap_LTLIBRARIES += libcharon-eapsim.la libcharon_eapsim_la_SOURCES = sa/authenticators/eap/eap_sim.h sa/authenticators/eap/eap_sim.c libcharon_eapsim_la_LDFLAGS = -module + + plugin_LTLIBRARIES = libcharon-eapsim-file.la + libcharon_eapsim_file_la_SOURCES = sa/authenticators/eap/sim/eap_sim_file.c + libcharon_eapsim_file_la_LDFLAGS = -module endif if USE_EAP_MD5 diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in index bbae1270a..41f1690e2 100644 --- a/src/charon/Makefile.in +++ b/src/charon/Makefile.in @@ -72,12 +72,14 @@ am__vpath_adj = case $$p in \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(backenddir)" "$(DESTDIR)$(eapdir)" \ - "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(ipsecdir)" + "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(plugindir)" \ + "$(DESTDIR)$(ipsecdir)" backendLTLIBRARIES_INSTALL = $(INSTALL) eapLTLIBRARIES_INSTALL = $(INSTALL) interfaceLTLIBRARIES_INSTALL = $(INSTALL) +pluginLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(backend_LTLIBRARIES) $(eap_LTLIBRARIES) \ - $(interface_LTLIBRARIES) + $(interface_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = @USE_LIBDBUS_TRUE@libcharon_dbus_la_DEPENDENCIES = \ @USE_LIBDBUS_TRUE@ $(am__DEPENDENCIES_1) @@ -123,6 +125,18 @@ libcharon_eapmd5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libcharon_eapmd5_la_LDFLAGS) $(LDFLAGS) -o $@ @USE_EAP_MD5_TRUE@am_libcharon_eapmd5_la_rpath = -rpath $(eapdir) +libcharon_eapsim_file_la_LIBADD = +am__libcharon_eapsim_file_la_SOURCES_DIST = \ + sa/authenticators/eap/sim/eap_sim_file.c +@USE_EAP_SIM_TRUE@am_libcharon_eapsim_file_la_OBJECTS = \ +@USE_EAP_SIM_TRUE@ eap_sim_file.lo +libcharon_eapsim_file_la_OBJECTS = \ + $(am_libcharon_eapsim_file_la_OBJECTS) +libcharon_eapsim_file_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libcharon_eapsim_file_la_LDFLAGS) $(LDFLAGS) -o $@ +@USE_EAP_SIM_TRUE@am_libcharon_eapsim_file_la_rpath = -rpath \ +@USE_EAP_SIM_TRUE@ $(plugindir) libcharon_eapsim_la_LIBADD = am__libcharon_eapsim_la_SOURCES_DIST = \ sa/authenticators/eap/eap_sim.h \ @@ -349,14 +363,16 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libcharon_dbus_la_SOURCES) $(libcharon_eapaka_la_SOURCES) \ $(libcharon_eapidentity_la_SOURCES) \ - $(libcharon_eapmd5_la_SOURCES) $(libcharon_eapsim_la_SOURCES) \ - $(libcharon_local_la_SOURCES) $(libcharon_sqlite_la_SOURCES) \ - $(libcharon_stroke_la_SOURCES) $(libcharon_xml_la_SOURCES) \ - $(charon_SOURCES) + $(libcharon_eapmd5_la_SOURCES) \ + $(libcharon_eapsim_file_la_SOURCES) \ + $(libcharon_eapsim_la_SOURCES) $(libcharon_local_la_SOURCES) \ + $(libcharon_sqlite_la_SOURCES) $(libcharon_stroke_la_SOURCES) \ + $(libcharon_xml_la_SOURCES) $(charon_SOURCES) DIST_SOURCES = $(am__libcharon_dbus_la_SOURCES_DIST) \ $(am__libcharon_eapaka_la_SOURCES_DIST) \ $(am__libcharon_eapidentity_la_SOURCES_DIST) \ $(am__libcharon_eapmd5_la_SOURCES_DIST) \ + $(am__libcharon_eapsim_file_la_SOURCES_DIST) \ $(am__libcharon_eapsim_la_SOURCES_DIST) \ $(am__libcharon_local_la_SOURCES_DIST) \ $(am__libcharon_sqlite_la_SOURCES_DIST) \ @@ -484,11 +500,13 @@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ +plugindir = @plugindir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +simreader = @simreader@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ @@ -601,7 +619,8 @@ INCLUDES = -I${linuxdir} -I$(top_srcdir)/src/libstrongswan \ -I$(top_srcdir)/src/charon -I$(top_srcdir)/src/stroke \ $(am__append_13) $(am__append_15) AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \ - -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" + -DIPSEC_EAPDIR=\"${eapdir}\" -DIPSEC_BACKENDDIR=\"${backenddir}\" -DIPSEC_INTERFACEDIR=\"${interfacedir}\" \ + -DSIM_READER_LIB=\"${simreader}\" charon_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \ -lgmp -lpthread -lm -ldl $(am__append_4) @@ -614,6 +633,9 @@ eap_LTLIBRARIES = $(am__append_5) $(am__append_6) $(am__append_7) \ @USE_EAP_IDENTITY_TRUE@libcharon_eapidentity_la_LDFLAGS = -module @USE_EAP_SIM_TRUE@libcharon_eapsim_la_SOURCES = sa/authenticators/eap/eap_sim.h sa/authenticators/eap/eap_sim.c @USE_EAP_SIM_TRUE@libcharon_eapsim_la_LDFLAGS = -module +@USE_EAP_SIM_TRUE@plugin_LTLIBRARIES = libcharon-eapsim-file.la +@USE_EAP_SIM_TRUE@libcharon_eapsim_file_la_SOURCES = sa/authenticators/eap/sim/eap_sim_file.c +@USE_EAP_SIM_TRUE@libcharon_eapsim_file_la_LDFLAGS = -module @USE_EAP_MD5_TRUE@libcharon_eapmd5_la_SOURCES = sa/authenticators/eap/eap_md5.h sa/authenticators/eap/eap_md5.c @USE_EAP_MD5_TRUE@libcharon_eapmd5_la_LDFLAGS = -module @USE_EAP_AKA_TRUE@libcharon_eapaka_la_SOURCES = sa/authenticators/eap/eap_aka.h sa/authenticators/eap/eap_aka.c @@ -754,6 +776,33 @@ clean-interfaceLTLIBRARIES: 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)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \ + else :; fi; \ + done + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \ + 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 libcharon-dbus.la: $(libcharon_dbus_la_OBJECTS) $(libcharon_dbus_la_DEPENDENCIES) $(libcharon_dbus_la_LINK) $(am_libcharon_dbus_la_rpath) $(libcharon_dbus_la_OBJECTS) $(libcharon_dbus_la_LIBADD) $(LIBS) libcharon-eapaka.la: $(libcharon_eapaka_la_OBJECTS) $(libcharon_eapaka_la_DEPENDENCIES) @@ -762,6 +811,8 @@ libcharon-eapidentity.la: $(libcharon_eapidentity_la_OBJECTS) $(libcharon_eapide $(libcharon_eapidentity_la_LINK) $(am_libcharon_eapidentity_la_rpath) $(libcharon_eapidentity_la_OBJECTS) $(libcharon_eapidentity_la_LIBADD) $(LIBS) libcharon-eapmd5.la: $(libcharon_eapmd5_la_OBJECTS) $(libcharon_eapmd5_la_DEPENDENCIES) $(libcharon_eapmd5_la_LINK) $(am_libcharon_eapmd5_la_rpath) $(libcharon_eapmd5_la_OBJECTS) $(libcharon_eapmd5_la_LIBADD) $(LIBS) +libcharon-eapsim-file.la: $(libcharon_eapsim_file_la_OBJECTS) $(libcharon_eapsim_file_la_DEPENDENCIES) + $(libcharon_eapsim_file_la_LINK) $(am_libcharon_eapsim_file_la_rpath) $(libcharon_eapsim_file_la_OBJECTS) $(libcharon_eapsim_file_la_LIBADD) $(LIBS) libcharon-eapsim.la: $(libcharon_eapsim_la_OBJECTS) $(libcharon_eapsim_la_DEPENDENCIES) $(libcharon_eapsim_la_LINK) $(am_libcharon_eapsim_la_rpath) $(libcharon_eapsim_la_OBJECTS) $(libcharon_eapsim_la_LIBADD) $(LIBS) libcharon-local.la: $(libcharon_local_la_OBJECTS) $(libcharon_local_la_DEPENDENCIES) @@ -838,6 +889,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_method.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryption_payload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/endpoint_notify.Po@am__quote@ @@ -957,6 +1009,13 @@ eap_md5.lo: sa/authenticators/eap/eap_md5.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_md5.lo `test -f 'sa/authenticators/eap/eap_md5.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_md5.c +eap_sim_file.lo: sa/authenticators/eap/sim/eap_sim_file.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_sim_file.lo -MD -MP -MF $(DEPDIR)/eap_sim_file.Tpo -c -o eap_sim_file.lo `test -f 'sa/authenticators/eap/sim/eap_sim_file.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim/eap_sim_file.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_sim_file.Tpo $(DEPDIR)/eap_sim_file.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sa/authenticators/eap/sim/eap_sim_file.c' object='eap_sim_file.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o eap_sim_file.lo `test -f 'sa/authenticators/eap/sim/eap_sim_file.c' || echo '$(srcdir)/'`sa/authenticators/eap/sim/eap_sim_file.c + eap_sim.lo: sa/authenticators/eap/eap_sim.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT eap_sim.lo -MD -MP -MF $(DEPDIR)/eap_sim.Tpo -c -o eap_sim.lo `test -f 'sa/authenticators/eap/eap_sim.c' || echo '$(srcdir)/'`sa/authenticators/eap/eap_sim.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/eap_sim.Tpo $(DEPDIR)/eap_sim.Plo @@ -2294,7 +2353,7 @@ check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: - for dir in "$(DESTDIR)$(backenddir)" "$(DESTDIR)$(eapdir)" "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(ipsecdir)"; do \ + for dir in "$(DESTDIR)$(backenddir)" "$(DESTDIR)$(eapdir)" "$(DESTDIR)$(interfacedir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -2325,7 +2384,7 @@ clean: clean-am clean-am: clean-backendLTLIBRARIES clean-eapLTLIBRARIES clean-generic \ clean-interfaceLTLIBRARIES clean-ipsecPROGRAMS clean-libtool \ - mostlyclean-am + clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) @@ -2344,7 +2403,8 @@ info: info-am info-am: install-data-am: install-backendLTLIBRARIES install-eapLTLIBRARIES \ - install-interfaceLTLIBRARIES install-ipsecPROGRAMS + install-interfaceLTLIBRARIES install-ipsecPROGRAMS \ + install-pluginLTLIBRARIES install-dvi: install-dvi-am @@ -2381,28 +2441,30 @@ ps: ps-am ps-am: uninstall-am: uninstall-backendLTLIBRARIES uninstall-eapLTLIBRARIES \ - uninstall-interfaceLTLIBRARIES uninstall-ipsecPROGRAMS + uninstall-interfaceLTLIBRARIES uninstall-ipsecPROGRAMS \ + uninstall-pluginLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean \ clean-backendLTLIBRARIES clean-eapLTLIBRARIES clean-generic \ clean-interfaceLTLIBRARIES clean-ipsecPROGRAMS clean-libtool \ - ctags distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am \ + 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-backendLTLIBRARIES install-data install-data-am \ install-dvi install-dvi-am install-eapLTLIBRARIES install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-interfaceLTLIBRARIES \ install-ipsecPROGRAMS install-man install-pdf install-pdf-am \ - 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-backendLTLIBRARIES \ - uninstall-eapLTLIBRARIES uninstall-interfaceLTLIBRARIES \ - uninstall-ipsecPROGRAMS + 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-backendLTLIBRARIES uninstall-eapLTLIBRARIES \ + uninstall-interfaceLTLIBRARIES uninstall-ipsecPROGRAMS \ + 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. diff --git a/src/charon/control/interface_manager.c b/src/charon/control/interface_manager.c index c14903c7d..4d5aa2ea6 100644 --- a/src/charon/control/interface_manager.c +++ b/src/charon/control/interface_manager.c @@ -171,14 +171,11 @@ static bool initiate_listener(interface_bus_listener_t *this, signal_t signal, static status_t initiate_execute(interface_job_t *job) { ike_sa_t *ike_sa; - ike_cfg_t *ike_cfg; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, - ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg), - peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg)); + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); listener->ike_sa = ike_sa; if (ike_sa->get_peer_cfg(ike_sa) == NULL) @@ -435,15 +432,11 @@ static bool route_listener(interface_bus_listener_t *this, signal_t signal, static status_t route_execute(interface_job_t *job) { ike_sa_t *ike_sa; - ike_cfg_t *ike_cfg; interface_bus_listener_t *listener = &job->listener; peer_cfg_t *peer_cfg = listener->peer_cfg; - ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); - - ike_sa = charon->ike_sa_manager->checkout_by_peer(charon->ike_sa_manager, - ike_cfg->get_my_host(ike_cfg), ike_cfg->get_other_host(ike_cfg), - peer_cfg->get_my_id(peer_cfg), peer_cfg->get_other_id(peer_cfg)); + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); listener->ike_sa = ike_sa; if (ike_sa->get_peer_cfg(ike_sa) == NULL) diff --git a/src/charon/control/interfaces/stroke_interface.c b/src/charon/control/interfaces/stroke_interface.c index b51d53ebd..3b4b246bd 100755 --- a/src/charon/control/interfaces/stroke_interface.c +++ b/src/charon/control/interfaces/stroke_interface.c @@ -535,6 +535,24 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) iterator = charon->backends->create_iterator(charon->backends); while (iterator->iterate(iterator, (void**)&peer_cfg)) { + host_t *my_vip_conf, *other_vip_conf; + bool my_vip_equals = FALSE, other_vip_equals = FALSE; + + my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg); + if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) || + (!my_vip_conf && !my_vip)) + { + my_vip_equals = TRUE; + } + DESTROY_IF(my_vip_conf); + other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL); + if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) || + (!other_vip_conf && !other_vip)) + { + other_vip_equals = TRUE; + } + DESTROY_IF(other_vip_conf); + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg)) && other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg)) @@ -545,7 +563,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out) && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1) && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type - && vendor == msg->add_conn.eap_vendor) + && vendor == msg->add_conn.eap_vendor + && my_vip_equals && other_vip_equals) { DBG1(DBG_CFG, "reusing existing configuration '%s'", peer_cfg->get_name(peer_cfg)); diff --git a/src/charon/encoding/payloads/eap_payload.c b/src/charon/encoding/payloads/eap_payload.c index 345114af0..da2498c5e 100644 --- a/src/charon/encoding/payloads/eap_payload.c +++ b/src/charon/encoding/payloads/eap_payload.c @@ -312,13 +312,13 @@ eap_payload_t *eap_payload_create_data(chunk_t data) /* * Described in header */ -eap_payload_t *eap_payload_create_code(eap_code_t code) +eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier) { eap_payload_t *this = eap_payload_create(); chunk_t data = chunk_alloca(4); *(data.ptr + 0) = code; - *(data.ptr + 1) = 0; + *(data.ptr + 1) = identifier; *(u_int16_t*)(data.ptr + 2) = htons(data.len); this->set_data(this, data); @@ -328,13 +328,13 @@ eap_payload_t *eap_payload_create_code(eap_code_t code) /* * Described in header */ -eap_payload_t *eap_payload_create_nak() +eap_payload_t *eap_payload_create_nak(u_int8_t identifier) { eap_payload_t *this = eap_payload_create(); chunk_t data = chunk_alloca(5); *(data.ptr + 0) = EAP_RESPONSE; - *(data.ptr + 1) = 0; + *(data.ptr + 1) = identifier; *(u_int16_t*)(data.ptr + 2) = htons(data.len); *(data.ptr + 4) = EAP_NAK; diff --git a/src/charon/encoding/payloads/eap_payload.h b/src/charon/encoding/payloads/eap_payload.h index 3addbb838..e4f8663c2 100644 --- a/src/charon/encoding/payloads/eap_payload.h +++ b/src/charon/encoding/payloads/eap_payload.h @@ -132,19 +132,22 @@ eap_payload_t *eap_payload_create_data(chunk_t data); * Could should be either EAP_SUCCESS/EAP_FAILURE, use * constructor above otherwise. * - * @return eap_payload_t object + * @param code EAP status code + * @param identifier EAP identifier to use in payload + * @return eap_payload_t object * * @ingroup payloads */ -eap_payload_t *eap_payload_create_code(eap_code_t code); +eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier); /** * @brief Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK. * - * @return eap_payload_t object + * @param identifier EAP identifier to use in payload + * @return eap_payload_t object * * @ingroup payloads */ -eap_payload_t *eap_payload_create_nak(); +eap_payload_t *eap_payload_create_nak(u_int8_t identifier); #endif /* EAP_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/id_payload.c b/src/charon/encoding/payloads/id_payload.c index eee5e92db..aef8f6b7e 100644 --- a/src/charon/encoding/payloads/id_payload.c +++ b/src/charon/encoding/payloads/id_payload.c @@ -9,6 +9,7 @@ * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -49,7 +50,7 @@ struct private_id_payload_t { /** * Next payload type. */ - payload_type_t next_payload; + u_int8_t next_payload; /** * Critical flag. diff --git a/src/charon/sa/authenticators/eap/eap_sim.c b/src/charon/sa/authenticators/eap/eap_sim.c index c9eb5ce8f..90898fb46 100644 --- a/src/charon/sa/authenticators/eap/eap_sim.c +++ b/src/charon/sa/authenticators/eap/eap_sim.c @@ -29,6 +29,21 @@ #define MAX_TRIES 3 +/* number of triplets for one authentication */ +#define TRIPLET_COUNT 3 + +typedef enum sim_subtype_t sim_subtype_t; + +/** + * Subtypes of SIM messages + */ +enum sim_subtype_t { + SIM_START = 10, + SIM_CHALLENGE = 11, + SIM_NOTIFICATION = 12, + SIM_CLIENT_ERROR = 14, +}; + ENUM(sim_subtype_names, SIM_START, SIM_CLIENT_ERROR, "SIM_START", "SIM_CHALLENGE", @@ -37,6 +52,40 @@ ENUM(sim_subtype_names, SIM_START, SIM_CLIENT_ERROR, "SIM_CLIENT_ERROR", ); +typedef enum sim_attribute_t sim_attribute_t; + +/** + * Attributes in SIM messages + */ +enum sim_attribute_t { + /** defines the end of attribute list */ + AT_END = -1, + AT_RAND = 1, + AT_AUTN = 2, + AT_RES = 3, + AT_AUTS = 4, + AT_PADDING = 6, + AT_NONCE_MT = 7, + AT_PERMANENT_ID_REQ = 10, + AT_MAC = 11, + AT_NOTIFICATION = 12, + AT_ANY_ID_REQ = 13, + AT_IDENTITY = 14, + AT_VERSION_LIST = 15, + AT_SELECTED_VERSION = 16, + AT_FULLAUTH_ID_REQ = 17, + AT_COUNTER = 19, + AT_COUNTER_TOO_SMALL = 20, + AT_NONCE_S = 21, + AT_CLIENT_ERROR_CODE = 22, + AT_IV = 129, + AT_ENCR_DATA = 130, + AT_NEXT_PSEUDONYM = 132, + AT_NEXT_REAUTH_ID = 133, + AT_CHECKCODE = 134, + AT_RESULT_IND = 135, +}; + ENUM_BEGIN(sim_attribute_names, AT_END, AT_CLIENT_ERROR_CODE, "AT_END", "AT_0", @@ -96,6 +145,11 @@ struct private_eap_sim_t { sim_algo_t alg; /** + * libraries get_triplet() function returning a triplet + */ + sim_get_triplet_t get_triplet; + + /** * handle of the loaded library */ void *handle; @@ -106,6 +160,16 @@ struct private_eap_sim_t { int tries; /** + * unique EAP identifier + */ + u_int8_t identifier; + + /** + * EAP message type this role sends + */ + u_int8_t type; + + /** * version this implementation uses */ chunk_t version; @@ -121,6 +185,11 @@ struct private_eap_sim_t { chunk_t nonce; /** + * concatenated SRES values + */ + chunk_t sreses; + + /** * k_encr key derived from MK */ chunk_t k_encr; @@ -147,6 +216,10 @@ struct private_eap_sim_t { #define MAC_LEN 16 /** length of the AT_RAND value */ #define RAND_LEN 16 +/** length of Kc */ +#define KC_LEN 8 +/** length of SRES */ +#define SRES_LEN 4 /** length of the k_encr key */ #define KENCR_LEN 16 /** length of the k_auth key */ @@ -156,6 +229,7 @@ struct private_eap_sim_t { /** length of the EMSK */ #define EMSK_LEN 64 +static char version[] = {0x00,0x01}; /* client error codes used in AT_CLIENT_ERROR_CODE */ char client_error_general_buf[] = {0x00, 0x01}; char client_error_unsupported_buf[] = {0x00, 0x02}; @@ -229,7 +303,7 @@ static eap_payload_t *build_payload(private_eap_sim_t *this, u_int8_t identifier chunk_t mac_data = chunk_empty; /* write EAP header, skip length bytes */ - *pos.ptr++ = EAP_RESPONSE; + *pos.ptr++ = this->type; *pos.ptr++ = identifier; pos.ptr += 2; pos.len -= 4; @@ -263,6 +337,7 @@ static eap_payload_t *build_payload(private_eap_sim_t *this, u_int8_t identifier break; } case AT_IDENTITY: + case AT_VERSION_LIST: { u_int16_t act_len = data.len; /* align up to four byte */ @@ -346,8 +421,8 @@ static eap_payload_t *build_payload(private_eap_sim_t *this, u_int8_t identifier /** * process an EAP-SIM/Request/Start message */ -static status_t process_start(private_eap_sim_t *this, eap_payload_t *in, - eap_payload_t **out) +static status_t peer_process_start(private_eap_sim_t *this, eap_payload_t *in, + eap_payload_t **out) { chunk_t message, data; sim_attribute_t attribute, include_id = AT_END; @@ -440,18 +515,56 @@ static status_t process_start(private_eap_sim_t *this, eap_payload_t *in, } /** + * derive EAP keys from kc + */ +static void derive_keys(private_eap_sim_t *this, chunk_t kcs) +{ + chunk_t tmp, mk; + hasher_t *hasher; + prf_t *prf; + int i; + + /* build MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ + tmp = chunk_cata("ccccc", this->peer->get_encoding(this->peer), kcs, + this->nonce, this->version_list, this->version); + hasher = hasher_create(HASH_SHA1); + mk = chunk_alloca(hasher->get_hash_size(hasher)); + hasher->get_hash(hasher, tmp, mk.ptr); + hasher->destroy(hasher); + DBG3(DBG_IKE, "MK = SHA1(%B\n) = %B", &tmp, &mk); + + /* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() + * FIPS PRF has 320 bit block size, we need 160 byte for keys + * => run prf four times */ + prf = prf_create(PRF_FIPS_SHA1_160); + prf->set_key(prf, mk); + tmp = chunk_alloca(prf->get_block_size(prf) * 4); + for (i = 0; i < 4; i++) + { + prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * i); + } + prf->destroy(prf); + chunk_free(&this->k_encr); + chunk_free(&this->k_auth); + chunk_free(&this->msk); + chunk_free(&this->emsk); + chunk_split(tmp, "aaaa", KENCR_LEN, &this->k_encr, KAUTH_LEN, &this->k_auth, + MSK_LEN, &this->msk, EMSK_LEN, &this->emsk); + DBG3(DBG_IKE, "K_encr %B\nK_auth %B\nMSK %B\nEMSK %B", + &this->k_encr, &this->k_auth, &this->msk, &this->emsk); +} + +/** * process an EAP-SIM/Request/Challenge message */ -static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in, - eap_payload_t **out) +static status_t peer_process_challenge(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) { - chunk_t message, data, tmp, kcs, kc, sreses, sres, mk; + chunk_t message, data, tmp, kcs, kc, sreses, sres; sim_attribute_t attribute; - u_int8_t identifier, i; + u_int8_t identifier; chunk_t mac = chunk_empty, rands = chunk_empty; signer_t *signer; - hasher_t *hasher; - prf_t *prf; if (this->tries-- <= 0) { @@ -541,7 +654,7 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in, if (this->alg(rands.ptr, RAND_LEN, sres.ptr, &sres_len, kc.ptr, &kc_len)) { - DBG1(DBG_IKE, "unable to get triplets from SIM"); + DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); *out = build_payload(this, identifier, SIM_CLIENT_ERROR, AT_CLIENT_ERROR_CODE, client_error_general, AT_END); @@ -554,34 +667,7 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in, rands = chunk_skip(rands, RAND_LEN); } - /* build MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - tmp = chunk_cata("ccccc", this->peer->get_encoding(this->peer), kcs, - this->nonce, this->version_list, this->version); - hasher = hasher_create(HASH_SHA1); - mk = chunk_alloca(hasher->get_hash_size(hasher)); - hasher->get_hash(hasher, tmp, mk.ptr); - hasher->destroy(hasher); - DBG3(DBG_IKE, "MK = SHA1(%B\n) = %B", &tmp, &mk); - - /* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() - * FIPS PRF has 320 bit block size, we need 160 byte for keys - * => run prf four times */ - prf = prf_create(PRF_FIPS_SHA1_160); - prf->set_key(prf, mk); - tmp = chunk_alloca(prf->get_block_size(prf) * 4); - for (i = 0; i < 4; i++) - { - prf->get_bytes(prf, chunk_empty, tmp.ptr + tmp.len / 4 * i); - } - prf->destroy(prf); - chunk_free(&this->k_encr); - chunk_free(&this->k_auth); - chunk_free(&this->msk); - chunk_free(&this->emsk); - chunk_split(tmp, "aaaa", KENCR_LEN, &this->k_encr, KAUTH_LEN, &this->k_auth, - MSK_LEN, &this->msk, EMSK_LEN, &this->emsk); - DBG3(DBG_IKE, "K_encr %B\nK_auth %B\nMSK %B\nEMSK %B", - &this->k_encr, &this->k_auth, &this->msk, &this->emsk); + derive_keys(this, kcs); /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT" */ signer = signer_create(AUTH_HMAC_SHA1_128); @@ -606,10 +692,144 @@ static status_t process_challenge(private_eap_sim_t *this, eap_payload_t *in, } /** + * process an EAP-SIM/Response/Challenge message + */ +static status_t server_process_challenge(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + chunk_t message, data; + sim_attribute_t attribute; + chunk_t mac = chunk_empty, tmp; + signer_t *signer; + + message = in->get_data(in); + read_header(&message); + + while ((attribute = read_attribute(&message, &data)) != AT_END) + { + switch (attribute) + { + case AT_MAC: + /* MAC has two reserved bytes */ + if (data.len == MAC_LEN + 2) + { /* clone and zero MAC for verification */ + mac = chunk_clonea(chunk_skip(data, 2)); + memset(data.ptr, 0, data.len); + } + break; + default: + DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", + sim_attribute_names, attribute); + break; + } + } + if (!mac.ptr) + { + DBG1(DBG_IKE, "no valid AT_MAC attribute received"); + return FAILED; + } + /* verify AT_MAC attribute, signature is over "EAP packet | n*SRES" */ + signer = signer_create(AUTH_HMAC_SHA1_128); + signer->set_key(signer, this->k_auth); + tmp = chunk_cata("cc", in->get_data(in), this->sreses); + if (!signer->verify_signature(signer, tmp, mac)) + { + DBG1(DBG_IKE, "AT_MAC verification failed"); + signer->destroy(signer); + return FAILED; + } + signer->destroy(signer); + return SUCCESS; +} + +/** + * process an EAP-SIM/Response/Start message + */ +static status_t server_process_start(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + chunk_t message, data; + sim_attribute_t attribute; + bool supported = FALSE; + chunk_t rands, rand, kcs, kc, sreses, sres; + char id[64]; + int len, i, rand_len, kc_len, sres_len; + + message = in->get_data(in); + read_header(&message); + + while ((attribute = read_attribute(&message, &data)) != AT_END) + { + switch (attribute) + { + case AT_NONCE_MT: + if (data.len == NONCE_LEN + 2) + { + this->nonce = chunk_clone(chunk_skip(data, 2)); + } + break; + case AT_SELECTED_VERSION: + if (chunk_equals(data, this->version)) + { + supported = TRUE; + } + break; + default: + DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", + sim_attribute_names, attribute); + break; + } + } + if (!supported || !this->nonce.ptr) + { + DBG1(DBG_IKE, "received incomplete EAP-SIM/Response/Start"); + return FAILED; + } + len = snprintf(id, sizeof(id), "%D", this->peer); + if (len > sizeof(id) || len < 0) + { + return FAILED; + } + + /* read triplets from provider */ + rand = rands = chunk_alloca(RAND_LEN * TRIPLET_COUNT); + kc = kcs = chunk_alloca(KC_LEN * TRIPLET_COUNT); + sres = sreses = chunk_alloca(SRES_LEN * TRIPLET_COUNT); + rands.len = 0; + kcs.len = 0; + sreses.len = 0; + for (i = 0; i < TRIPLET_COUNT; i++) + { + rand_len = RAND_LEN; + kc_len = KC_LEN; + sres_len = SRES_LEN; + if (this->get_triplet(id, rand.ptr, &rand_len, sres.ptr, &sres_len, + kc.ptr, &kc_len)) + { + DBG1(DBG_IKE, "getting EAP-SIM triplet %d failed", i); + return FAILED; + } + rands.len += rand_len; + kcs.len += kc_len; + sreses.len += sres_len; + rand = chunk_skip(rand, rand_len); + kc = chunk_skip(kc, kc_len); + sres = chunk_skip(sres, sres_len); + } + derive_keys(this, kcs); + + /* build MAC over "EAP packet | NONCE_MT" */ + *out = build_payload(this, this->identifier++, SIM_CHALLENGE, AT_RAND, + rands, AT_MAC, this->nonce, AT_END); + this->sreses = chunk_clone(sreses); + return NEED_MORE; +} + +/** * process an EAP-SIM/Request/Notification message */ -static status_t process_notification(private_eap_sim_t *this, eap_payload_t *in, - eap_payload_t **out) +static status_t peer_process_notification(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) { chunk_t message, data; sim_attribute_t attribute; @@ -656,12 +876,44 @@ static status_t process_notification(private_eap_sim_t *this, eap_payload_t *in, return NEED_MORE; } +/** + * Process a client error + */ +static status_t server_process_client_error(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + chunk_t message, data; + sim_attribute_t attribute; + + message = in->get_data(in); + read_header(&message); + + while ((attribute = read_attribute(&message, &data)) != AT_END) + { + if (attribute == AT_CLIENT_ERROR_CODE) + { + u_int16_t code = 0; + if (data.len == 2) + { + code = ntohs(*(u_int16_t*)data.ptr); + } + DBG1(DBG_IKE, "received %N error %d", + sim_attribute_names, attribute, code); + } + else + { + DBG1(DBG_IKE, "ignoring EAP_SIM attribute %N", + sim_attribute_names, attribute); + } + } + return FAILED; +} /** * Implementation of eap_method_t.process for the peer */ -static status_t process(private_eap_sim_t *this, - eap_payload_t *in, eap_payload_t **out) +static status_t peer_process(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) { sim_subtype_t type; chunk_t message; @@ -672,11 +924,11 @@ static status_t process(private_eap_sim_t *this, switch (type) { case SIM_START: - return process_start(this, in, out); + return peer_process_start(this, in, out); case SIM_CHALLENGE: - return process_challenge(this, in, out); + return peer_process_challenge(this, in, out); case SIM_NOTIFICATION: - return process_notification(this, in, out); + return peer_process_notification(this, in, out); default: DBG1(DBG_IKE, "unable to process EAP_SIM subtype %N", sim_subtype_names, type); @@ -687,15 +939,55 @@ static status_t process(private_eap_sim_t *this, } /** + * Implementation of eap_method_t.process for the server + */ +static status_t server_process(private_eap_sim_t *this, + eap_payload_t *in, eap_payload_t **out) +{ + sim_subtype_t type; + chunk_t message; + + message = in->get_data(in); + type = read_header(&message); + + switch (type) + { + case SIM_START: + return server_process_start(this, in, out); + case SIM_CHALLENGE: + return server_process_challenge(this, in, out); + case SIM_CLIENT_ERROR: + return server_process_client_error(this, in, out); + default: + DBG1(DBG_IKE, "unable to process EAP_SIM subtype %N", + sim_subtype_names, type); + return FAILED; + } +} + +/** * Implementation of eap_method_t.initiate for the peer */ -static status_t initiate(private_eap_sim_t *this, eap_payload_t **out) +static status_t peer_initiate(private_eap_sim_t *this, eap_payload_t **out) { /* peer never initiates */ return FAILED; } /** + * Implementation of eap_method_t.initiate for the server + */ +static status_t server_initiate(private_eap_sim_t *this, eap_payload_t **out) +{ + /* version_list to derive MK, no padding */ + this->version_list = chunk_clone(this->version); + /* build_payloads adds padding itself */ + *out = build_payload(this, this->identifier++, SIM_START, + AT_VERSION_LIST, this->version, AT_END); + return NEED_MORE; +} + +/** * Implementation of eap_method_t.get_type. */ static eap_type_t get_type(private_eap_sim_t *this, u_int32_t *vendor) @@ -732,6 +1024,7 @@ static void destroy(private_eap_sim_t *this) { dlclose(this->handle); chunk_free(&this->nonce); + chunk_free(&this->sreses); chunk_free(&this->version_list); chunk_free(&this->k_auth); chunk_free(&this->k_encr); @@ -748,60 +1041,85 @@ eap_sim_t *eap_create(eap_role_t role, { private_eap_sim_t *this; randomizer_t *randomizer; - static char version[] = {0x00,0x01}; - - if (role != EAP_PEER) - { - return NULL; - } - this = malloc_thing(private_eap_sim_t); + void *symbol; + char *name; + + this = malloc_thing(private_eap_sim_t); + this->alg = NULL; + this->get_triplet = NULL; + this->nonce = chunk_empty; + this->sreses = chunk_empty; + this->peer = peer; + this->tries = MAX_TRIES; + this->version.ptr = version; + this->version.len = sizeof(version); + this->version_list = chunk_empty; + this->k_auth = chunk_empty; + this->k_encr = chunk_empty; + this->msk = chunk_empty; + this->emsk = chunk_empty; + this->identifier = random(); this->handle = dlopen(SIM_READER_LIB, RTLD_LAZY); if (this->handle == NULL) { - DBG1(DBG_IKE, "unable to open SIM reader '%s'", SIM_READER_LIB); + DBG1(DBG_IKE, "unable to open SIM reader '%s'", SIM_READER_LIB); free(this); return NULL; } - this->alg = dlsym(this->handle, SIM_READER_ALG); - if (this->alg == NULL) + switch (role) { - DBG1(DBG_IKE, "unable to open SIM reader function '%s' in '%s'", - SIM_READER_ALG, SIM_READER_LIB); + case EAP_PEER: + name = SIM_READER_ALG; + break; + case EAP_SERVER: + name = SIM_READER_GET_TRIPLET; + break; + default: + free(this); + return NULL; + } + symbol = dlsym(this->handle, name); + if (symbol == NULL) + { + DBG1(DBG_IKE, "unable to open SIM function '%s' in '%s'", + name, SIM_READER_LIB); dlclose(this->handle); free(this); return NULL; } - - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, - &this->nonce)) + switch (role) { - DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); - randomizer->destroy(randomizer); - free(this); - return NULL; + case EAP_SERVER: + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))server_initiate; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))server_process; + this->get_triplet = symbol; + this->type = EAP_REQUEST; + break; + case EAP_PEER: + this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))peer_initiate; + this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; + this->alg = symbol; + this->type = EAP_RESPONSE; + randomizer = randomizer_create(); + if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, + &this->nonce)) + { + DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); + randomizer->destroy(randomizer); + free(this); + return NULL; + } + randomizer->destroy(randomizer); + break; + default: + free(this); + return NULL; } - randomizer->destroy(randomizer); - - /* public functions */ - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; - /* private data */ - this->peer = peer; - this->tries = MAX_TRIES; - this->version.ptr = version; - this->version.len = sizeof(version); - this->version_list = chunk_empty; - this->k_auth = chunk_empty; - this->k_encr = chunk_empty; - this->msk = chunk_empty; - this->emsk = chunk_empty; - return &this->public; } diff --git a/src/charon/sa/authenticators/eap/eap_sim.h b/src/charon/sa/authenticators/eap/eap_sim.h index 10640babe..d50cf7397 100644 --- a/src/charon/sa/authenticators/eap/eap_sim.h +++ b/src/charon/sa/authenticators/eap/eap_sim.h @@ -24,59 +24,13 @@ #define EAP_SIM_H_ typedef struct eap_sim_t eap_sim_t; -typedef enum sim_subtype_t sim_subtype_t; -typedef enum sim_attribute_t sim_attribute_t; #include <sa/authenticators/eap/eap_method.h> -/** - * Subtypes of SIM messages - */ -enum sim_subtype_t { - SIM_START = 10, - SIM_CHALLENGE = 11, - SIM_NOTIFICATION = 12, - SIM_CLIENT_ERROR = 14, -}; - -/** - * enum names for sim_subtype_t - */ -extern enum_name_t *sim_subtype_names; - -enum sim_attribute_t { - /** defines the end of attribute list */ - AT_END = -1, - AT_RAND = 1, - AT_AUTN = 2, - AT_RES = 3, - AT_AUTS = 4, - AT_PADDING = 6, - AT_NONCE_MT = 7, - AT_PERMANENT_ID_REQ = 10, - AT_MAC = 11, - AT_NOTIFICATION = 12, - AT_ANY_ID_REQ = 13, - AT_IDENTITY = 14, - AT_VERSION_LIST = 15, - AT_SELECTED_VERSION = 16, - AT_FULLAUTH_ID_REQ = 17, - AT_COUNTER = 19, - AT_COUNTER_TOO_SMALL = 20, - AT_NONCE_S = 21, - AT_CLIENT_ERROR_CODE = 22, - AT_IV = 129, - AT_ENCR_DATA = 130, - AT_NEXT_PSEUDONYM = 132, - AT_NEXT_REAUTH_ID = 133, - AT_CHECKCODE = 134, - AT_RESULT_IND = 135, -}; - -/** - * enum names for sim_subtype_t - */ -extern enum_name_t *sim_attribute_names; +/** the library containing with the triplet functions */ +#ifndef SIM_READER_LIB +#error SIM_READER_LIB not specified, use --with-sim-reader option +#endif /* SIM_READER_LIB */ /** * @brief Cardreaders SIM function. @@ -93,24 +47,42 @@ typedef int (*sim_algo_t)(const unsigned char *rand, int rand_length, unsigned char *sres, int *sres_length, unsigned char *kc, int *kc_length); -#ifndef SIM_READER_LIB -/** the library containing the cardreader with the SIM function */ -#error SIM_READER_LIB not specified, use --with-sim-reader option -#endif /* SIM_READER_LIB */ - #ifndef SIM_READER_ALG /** the SIM_READER_LIB's algorithm, uses sim_algo_t signature */ #define SIM_READER_ALG "sim_run_alg" #endif /* SIM_READER_ALG */ +/** + * @brief Function to get a SIM triplet. + * + * @param identity identity (imsi) to get a triplet for + * @param rand buffer to get RAND + * @param rand_length size of buffer in rand, returns bytes written to RAND + * @param sres buffer to get SRES + * @param sres_length size of buffer in sres, returns bytes written to SRES + * @param kc buffer to get Kc + * @param kc_length size of buffer in Kc, returns bytes written to Kc + * @return zero on success + */ +typedef int (*sim_get_triplet_t)(char *identity, + unsigned char *rand, int *rand_length, + unsigned char *sres, int *sres_length, + unsigned char *kc, int *kc_length); + +#ifndef SIM_READER_GET_TRIPLET +/** the SIM_READER_LIB's get-triplet function, uses sim_get_triplet_t signature */ +#define SIM_READER_GET_TRIPLET "sim_get_triplet" +#endif /* SIM_READER_GET_TRIPLET */ /** * @brief Implementation of the eap_method_t interface using EAP-SIM. * * This EAP-SIM client implementation uses another pluggable library to - * access the SIM card. This module is specified using the SIM_READER_LIB - * definition. The function to run the algorithm has the sim_algo_t type and - * is named as SIM_READER_ALG is defined. + * access the SIM card/triplet provider. This module is specified using the + * SIM_READER_LIB definition. It has to privde a sim_run_alg() function to + * calculate a triplet (client), and/or a sim_get_triplet() function to get + * a triplet (server). These functions are named to the SIM_READER_ALG and + * the SIM_READER_GET_TRIPLET definitions. * * @b Constructors: * - eap_create() of this module @@ -129,6 +101,7 @@ struct eap_sim_t { /** * @brief Creates the EAP method EAP-SIM. * + * @param role role of the module, client/server * @param server ID of the EAP server * @param peer ID of the EAP client * @return eap_sim_t object diff --git a/src/charon/sa/authenticators/eap/sim/eap_sim_file.c b/src/charon/sa/authenticators/eap/sim/eap_sim_file.c new file mode 100644 index 000000000..2ab45a578 --- /dev/null +++ b/src/charon/sa/authenticators/eap/sim/eap_sim_file.c @@ -0,0 +1,288 @@ +/**
+ * @file eap_sim.h
+ *
+ * @brief Interface of eap_sim_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2007 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 <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <daemon.h>
+
+#define IMSI_LEN 64
+#define RAND_LEN 16
+#define SRES_LEN 4
+#define KC_LEN 8
+
+typedef struct triplet_t triplet_t;
+
+struct triplet_t {
+ unsigned char imsi[IMSI_LEN];
+ unsigned char rand[RAND_LEN];
+ unsigned char sres[SRES_LEN];
+ unsigned char kc[KC_LEN];
+};
+
+static triplet_t *triplets = NULL;
+static int triplet_count = 0;
+
+#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat"
+
+/**
+ * convert a single HEX char to its integer value
+ */
+static int hexchr(char chr)
+{
+ switch (chr)
+ {
+ case '0'...'9':
+ return chr - '0';
+ case 'A'...'F':
+ return 10 + chr - 'A';
+ case 'a'...'f':
+ return 10 + chr - 'a';
+ }
+ return 0;
+}
+
+/**
+ * convert a HEX string into a char array bin, limited by array length len
+ */
+static void hex2bin(char *hex, unsigned char *bin, size_t len)
+{
+ char *pos;
+ int i, even = 1;
+
+ pos = hex - 1;
+ /* find the end, as we convert bottom up */
+ while (TRUE)
+ {
+ switch (*(pos+1))
+ {
+ case '0'...'9':
+ case 'A'...'F':
+ case 'a'...'f':
+ pos++;
+ continue;
+ }
+ break;
+ }
+ /* convert two hex chars into a single bin byte */
+ for (i = 0; pos >= hex && i < len; pos--)
+ {
+ if (even)
+ {
+ bin[len - 1 - i] = hexchr(*pos);
+ }
+ else
+ {
+ bin[len - 1 - i] |= 16 * hexchr(*pos);
+ i++;
+ }
+ even = !even;
+ }
+}
+
+/**
+ * free up allocated triplets
+ */
+static void __attribute__ ((destructor)) free_triplets()
+{
+ free(triplets);
+}
+
+/**
+ * read the triplets from the file, using freeradius triplet file syntax:
+ * http://www.freeradius.org/radiusd/doc/rlm_sim_triplets
+ */
+static void __attribute__ ((constructor)) read_triplets()
+{
+ char line[512], *data[4], *pos;
+ FILE *file;
+ int i, nr = 0;
+ triplet_t *triplet;
+
+ file = fopen(TRIPLET_FILE, "r");
+ if (file == NULL)
+ {
+ DBG1(DBG_CFG, "opening triplet file %s failed: %s",
+ TRIPLET_FILE, strerror(errno));
+ return;
+ }
+
+ if (triplets)
+ {
+ free(triplets);
+ triplets = NULL;
+ triplet_count = 0;
+ }
+
+ /* read line by line */
+ while (fgets(line, sizeof(line), file))
+ {
+ nr++;
+ /* skip comments, empty lines */
+ switch (line[0])
+ {
+ case '\n':
+ case '\r':
+ case '#':
+ case '\0':
+ continue;
+ default:
+ break;
+ }
+ /* read comma separated values */
+ pos = line;
+ for (i = 0; i < 4; i++)
+ {
+ data[i] = pos;
+ pos = strchr(pos, ',');
+ if (pos)
+ {
+ *pos = '\0';
+ pos++;
+ }
+ else if (i != 3)
+ {
+ DBG1(DBG_CFG, "error in triplet file, line %d", nr);
+ fclose(file);
+ return;
+ }
+ }
+ /* allocate new triplet */
+ triplet_count++;
+ triplets = realloc(triplets, triplet_count * sizeof(triplet_t));
+ triplet = &triplets[triplet_count - 1];
+ memset(triplet, 0, sizeof(triplet_t));
+
+ /* convert/copy triplet data */
+ for (i = 0; i < IMSI_LEN - 1; i++)
+ {
+ switch (data[0][i])
+ {
+ case '\n':
+ case '\r':
+ case '\0':
+ break;
+ default:
+ triplet->imsi[i] = data[0][i];
+ continue;
+ }
+ break;
+ }
+ hex2bin(data[1], triplet->rand, RAND_LEN);
+ hex2bin(data[2], triplet->sres, SRES_LEN);
+ hex2bin(data[3], triplet->kc, KC_LEN);
+
+ DBG4(DBG_CFG, "triplet: imsi %b\nrand %b\nsres %b\nkc %b",
+ triplet->imsi, IMSI_LEN, triplet->rand, RAND_LEN,
+ triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
+ }
+ fclose(file);
+ DBG2(DBG_CFG, "read %d triplets from %s", triplet_count, TRIPLET_FILE);
+}
+
+/**
+ * Run the sim algorithm, see eap_sim.h
+ */
+int sim_run_alg(const unsigned char *rand, int rand_length,
+ unsigned char *sres, int *sres_length,
+ unsigned char *kc, int *kc_length)
+{
+ int current;
+
+ if (rand_length != RAND_LEN ||
+ *sres_length < SRES_LEN ||
+ *kc_length < KC_LEN)
+ {
+ return 1;
+ }
+
+ for (current = 0; current < triplet_count; current++)
+ {
+ if (memcmp(triplets[current].rand, rand, RAND_LEN) == 0)
+ {
+ memcpy(sres, triplets[current].sres, SRES_LEN);
+ memcpy(kc, triplets[current].kc, KC_LEN);
+ *sres_length = SRES_LEN;
+ *kc_length = KC_LEN;
+ return 0;
+ }
+ }
+ return 2;
+}
+
+/**
+ * Get a single triplet, see_eap_sim.h
+ */
+int sim_get_triplet(char *imsi,
+ unsigned char *rand, int *rand_length,
+ unsigned char *sres, int *sres_length,
+ unsigned char *kc, int *kc_length)
+{
+ int current;
+ triplet_t *triplet;
+ static int skip = -1;
+
+ DBG2(DBG_CFG, "getting triplet for %s", imsi);
+
+ if (*rand_length < RAND_LEN ||
+ *sres_length < SRES_LEN ||
+ *kc_length < KC_LEN)
+ {
+ return 1;
+ }
+ if (triplet_count == 0)
+ {
+ return 2;
+ }
+ for (current = 0; current < triplet_count; current++)
+ {
+ triplet = &triplets[current];
+
+ if (streq(imsi, triplet->imsi))
+ {
+ /* skip triplet if already used */
+ if (skip >= current)
+ {
+ continue;
+ }
+ *rand_length = RAND_LEN;
+ *sres_length = SRES_LEN;
+ *kc_length = KC_LEN;
+ memcpy(rand, triplet->rand, RAND_LEN);
+ memcpy(sres, triplet->sres, SRES_LEN);
+ memcpy(kc, triplet->kc, KC_LEN);
+ /* remember used triplet */
+ skip = current;
+ return 0;
+ }
+ }
+ if (skip > -1)
+ {
+ /* no triplet left, reuse triplets */
+ skip = -1;
+ return sim_get_triplet(imsi, rand, rand_length,
+ sres, sres_length, kc, kc_length);
+ }
+ return 2;
+}
+
diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index 6250604a6..edd75da43 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -147,7 +147,7 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, { DBG1(DBG_IKE, "client requested EAP authentication, but configuration forbids it"); - *out = eap_payload_create_code(EAP_FAILURE); + *out = eap_payload_create_code(EAP_FAILURE, 0); return FAILED; } @@ -169,14 +169,14 @@ static status_t initiate(private_eap_authenticator_t *this, eap_type_t type, DBG1(DBG_IKE, "configured EAP server method not supported, sending %N", eap_code_names, EAP_FAILURE); - *out = eap_payload_create_code(EAP_FAILURE); + *out = eap_payload_create_code(EAP_FAILURE, 0); return FAILED; } if (this->method->initiate(this->method, out) != NEED_MORE) { DBG1(DBG_IKE, "failed to initiate EAP exchange, sending %N", eap_type_names, type, eap_code_names, EAP_FAILURE); - *out = eap_payload_create_code(EAP_FAILURE); + *out = eap_payload_create_code(EAP_FAILURE, 0); return FAILED; } return NEED_MORE; @@ -234,7 +234,7 @@ static status_t process_peer(private_eap_authenticator_t *this, { DBG1(DBG_IKE, "EAP server requested unsupported " "EAP method, sending EAP_NAK"); - *out = eap_payload_create_nak(); + *out = eap_payload_create_nak(in->get_identifier(in)); return NEED_MORE; } } @@ -303,7 +303,7 @@ static status_t process_server(private_eap_authenticator_t *this, DBG1(DBG_IKE, "EAP method %N succeded, %sMSK established", eap_type_names, type, this->msk.ptr ? "" : "no "); } - *out = eap_payload_create_code(EAP_SUCCESS); + *out = eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in)); return SUCCESS; case FAILED: default: @@ -319,7 +319,7 @@ static status_t process_server(private_eap_authenticator_t *this, eap_type_names, type, this->ike_sa->get_other_id(this->ike_sa)); } - *out = eap_payload_create_code(EAP_FAILURE); + *out = eap_payload_create_code(EAP_FAILURE, in->get_identifier(in)); return FAILED; } } @@ -346,7 +346,8 @@ static status_t process(private_eap_authenticator_t *this, eap_payload_t *in, { DBG1(DBG_IKE, "received %N, sending %N", eap_code_names, code, eap_code_names, EAP_FAILURE); - *out = eap_payload_create_code(EAP_FAILURE); + *out = eap_payload_create_code(EAP_FAILURE, + in->get_identifier(in)); return FAILED; } } diff --git a/src/charon/sa/connect_manager.c b/src/charon/sa/connect_manager.c index d0f3cde8d..06755fa9c 100644 --- a/src/charon/sa/connect_manager.c +++ b/src/charon/sa/connect_manager.c @@ -27,6 +27,7 @@ #include <daemon.h> #include <utils/linked_list.h> +#include <crypto/hashers/hasher.h> #include <processing/jobs/callback_job.h> #include <processing/jobs/initiate_mediation_job.h> @@ -493,29 +494,18 @@ static initiate_data_t *initiate_data_create(check_list_t *checklist, initiated_ /** * Find an initiated connection by the peers' ids */ +static bool match_initiated_by_ids(initiated_t *current, identification_t *id, + identification_t *peer_id) +{ + return id->equals(id, current->id) && peer_id->equals(peer_id, current->peer_id); +} + static status_t get_initiated_by_ids(private_connect_manager_t *this, identification_t *id, identification_t *peer_id, initiated_t **initiated) { - iterator_t *iterator; - initiated_t *current; - status_t status = NOT_FOUND; - - iterator = this->initiated->create_iterator(this->initiated, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (id->equals(id, current->id) && peer_id->equals(peer_id, current->peer_id)) - { - if (initiated) - { - *initiated = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return this->initiated->find_first(this->initiated, + (linked_list_match_t)match_initiated_by_ids, + (void**)initiated, id, peer_id); } /** @@ -541,56 +531,32 @@ static void remove_initiated(private_connect_manager_t *this, initiated_t *initi /** * Finds a waiting sa */ -static status_t get_waiting_sa(initiated_t *initiated, ike_sa_id_t *ike_sa_id, waiting_sa_t **waiting_sa) +static bool match_waiting_sa(waiting_sa_t *current, ike_sa_id_t *ike_sa_id) { - iterator_t *iterator; - waiting_sa_t *current; - status_t status = NOT_FOUND; - - iterator = initiated->mediated->create_iterator(initiated->mediated, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (ike_sa_id->equals(ike_sa_id, current->ike_sa_id)) - { - if (waiting_sa) - { - *waiting_sa = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); + return ike_sa_id->equals(ike_sa_id, current->ike_sa_id); +} - return status; +static status_t get_waiting_sa(initiated_t *initiated, ike_sa_id_t *ike_sa_id, waiting_sa_t **waiting_sa) +{ + return initiated->mediated->find_first(initiated->mediated, + (linked_list_match_t)match_waiting_sa, + (void**)waiting_sa, ike_sa_id); } /** * Find the checklist with a specific session ID */ +static bool match_checklist_by_id(check_list_t *current, chunk_t *session_id) +{ + return chunk_equals(*session_id, current->session_id); +} + static status_t get_checklist_by_id(private_connect_manager_t *this, chunk_t session_id, check_list_t **check_list) { - iterator_t *iterator; - check_list_t *current; - status_t status = NOT_FOUND; - - iterator = this->checklists->create_iterator(this->checklists, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (chunk_equals(session_id, current->session_id)) - { - if (check_list) - { - *check_list = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return this->checklists->find_first(this->checklists, + (linked_list_match_t)match_checklist_by_id, + (void**)check_list, &session_id); } /** @@ -616,28 +582,16 @@ static void remove_checklist(private_connect_manager_t *this, check_list_t *chec /** * Checks if a list of endpoint_notify_t contains a certain host_t */ +static bool match_endpoint_by_host(endpoint_notify_t *current, host_t *host) +{ + return host->equals(host, current->get_host(current)); +} + static status_t endpoints_contain(linked_list_t *endpoints, host_t *host, endpoint_notify_t **endpoint) { - iterator_t *iterator; - endpoint_notify_t *current; - status_t status = NOT_FOUND; - - iterator = endpoints->create_iterator(endpoints, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (host->equals(host, current->get_host(current))) - { - if (endpoint) - { - *endpoint = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return endpoints->find_first(endpoints, + (linked_list_match_t)match_endpoint_by_host, + (void**)endpoint, host); } /** @@ -715,88 +669,56 @@ static void insert_pair_by_priority(linked_list_t *pairs, endpoint_pair_t *pair) /** * Searches a list of endpoint_pair_t for a pair with specific host_ts */ +static bool match_pair_by_hosts(endpoint_pair_t *current, host_t *local, host_t *remote) +{ + return local->equals(local, current->local) && remote->equals(remote, current->remote); +} + static status_t get_pair_by_hosts(linked_list_t *pairs, host_t *local, host_t *remote, endpoint_pair_t **pair) { - iterator_t *iterator; - endpoint_pair_t *current; - status_t status = NOT_FOUND; - - iterator = pairs->create_iterator(pairs, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (local->equals(local, current->local) && - remote->equals(remote, current->remote)) - { - if (pair) - { - *pair = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return pairs->find_first(pairs, + (linked_list_match_t)match_pair_by_hosts, + (void**)pair, local, remote); } /** * Searches for a pair with a specific id */ +static bool match_pair_by_id(endpoint_pair_t *current, u_int32_t *id) +{ + return current->id == *id; +} + static status_t get_pair_by_id(check_list_t *checklist, u_int32_t id, endpoint_pair_t **pair) { - iterator_t *iterator; - endpoint_pair_t *current; - status_t status = NOT_FOUND; - - iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->id == id) - { - if (pair) - { - *pair = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return checklist->pairs->find_first(checklist->pairs, + (linked_list_match_t)match_pair_by_id, + (void**)pair, &id); } /** * Returns the best pair of state CHECK_SUCCEEDED from a checklist. */ +static bool match_succeeded_pair(endpoint_pair_t *current) +{ + return current->state == CHECK_SUCCEEDED; +} + static status_t get_best_valid_pair(check_list_t *checklist, endpoint_pair_t **pair) { - iterator_t *iterator; - endpoint_pair_t *current; - status_t status = NOT_FOUND; - - iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); - while (iterator->iterate(iterator, (void**)¤t)) - { - if (current->state == CHECK_SUCCEEDED) - { - if (pair) - { - *pair = current; - } - status = SUCCESS; - break; - } - } - iterator->destroy(iterator); - - return status; + return checklist->pairs->find_first(checklist->pairs, + (linked_list_match_t)match_succeeded_pair, + (void**)pair); } /** - * Returns and removes the first triggered pair in state CHECK_WAITING. + * Returns and *removes* the first triggered pair in state CHECK_WAITING. */ +static bool match_waiting_pair(endpoint_pair_t *current) +{ + return current->state == CHECK_WAITING; +} + static status_t get_triggered_pair(check_list_t *checklist, endpoint_pair_t **pair) { iterator_t *iterator; @@ -1148,21 +1070,8 @@ static job_requeue_t sender(sender_data_t *data) { DBG1(DBG_IKE, "no triggered check queued, sending an ordinary check"); - iterator_t *iterator; - bool found_one = FALSE; - - iterator = checklist->pairs->create_iterator(checklist->pairs, TRUE); - while (iterator->iterate(iterator, (void**)&pair)) - { - if (pair->state == CHECK_WAITING) - { - found_one = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (!found_one) + if (checklist->pairs->find_first(checklist->pairs, + (linked_list_match_t)match_waiting_pair, (void**)&pair) != SUCCESS) { pthread_mutex_unlock(&(this->mutex)); DBG1(DBG_IKE, "no pairs in waiting state, aborting"); diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 9cada2cb5..93aa08965 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -2090,7 +2090,14 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) { this->dns_servers->insert_first(this->dns_servers, ip); } - + + /* inherit NAT-T conditions */ + this->conditions = other->conditions; + if (this->conditions & COND_NAT_HERE) + { + send_keepalive(this); + } + /* adopt all children */ while (other->child_sas->remove_last(other->child_sas, (void**)&child_sa) == SUCCESS) diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 5014ea0e2..5e7f78af0 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -483,16 +483,23 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, } /** - * Implementation of of ike_sa_manager.checkout_by_peer. + * Implementation of of ike_sa_manager.checkout_by_config. */ -static ike_sa_t* checkout_by_peer(private_ike_sa_manager_t *this, - host_t *my_host, host_t *other_host, - identification_t *my_id, - identification_t *other_id) +static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, + peer_cfg_t *peer_cfg) { iterator_t *iterator; entry_t *entry; ike_sa_t *ike_sa = NULL; + identification_t *my_id, *other_id; + host_t *my_host, *other_host; + ike_cfg_t *ike_cfg; + + ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); + my_host = ike_cfg->get_my_host(ike_cfg); + other_host = ike_cfg->get_other_host(ike_cfg); + my_id = peer_cfg->get_my_id(peer_cfg); + other_id = peer_cfg->get_other_id(peer_cfg); pthread_mutex_lock(&(this->mutex)); @@ -535,7 +542,9 @@ static ike_sa_t* checkout_by_peer(private_ike_sa_manager_t *this, (other_host->is_anyaddr(other_host) || other_host->ip_equals(other_host, found_other_host)) && found_my_id->matches(found_my_id, my_id, &wc) && - found_other_id->matches(found_other_id, other_id, &wc)) + found_other_id->matches(found_other_id, other_id, &wc) && + streq(peer_cfg->get_name(peer_cfg), + entry->ike_sa->get_name(entry->ike_sa))) { /* looks good, we take this one */ DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]", @@ -902,7 +911,7 @@ ike_sa_manager_t *ike_sa_manager_create() this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout; this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new; this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message; - this->public.checkout_by_peer = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_peer; + this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config; this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id; this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name; this->public.create_iterator = (iterator_t*(*)(ike_sa_manager_t*))create_iterator; diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h index 1125e5d16..a73a106ba 100644 --- a/src/charon/sa/ike_sa_manager.h +++ b/src/charon/sa/ike_sa_manager.h @@ -29,6 +29,7 @@ typedef struct ike_sa_manager_t ike_sa_manager_t; #include <library.h> #include <sa/ike_sa.h> #include <encoding/message.h> +#include <config/peer_cfg.h> /** * @brief The IKE_SA-Manager is responsible for managing all initiated and responded IKE_SA's. @@ -94,25 +95,21 @@ struct ike_sa_manager_t { ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message); /** - * @brief Checkout an existing IKE_SA by hosts and identifications. + * @brief Checkout an IKE_SA for initiation by a peer_config. * - * Allows the lookup of an IKE_SA by user IDs and hosts. It returns the - * first found occurence, if there are multiple candidates. Supplied IDs - * may contain wildcards, hosts may be %any. + * To initiate, a CHILD_SA may be established within an existing IKE_SA. + * This call checks for an existing IKE_SA by comparing the configuration. + * If the CHILD_SA can be created in an existing IKE_SA, the matching SA + * is returned. * If no IKE_SA is found, a new one is created. This is also the case when * the found IKE_SA is in the DELETING state. * * @param this the manager object - * @param my_host address of our host - * @param other_id address of remote host - * @param my_id ID used by us - * @param other_id ID used by remote + * @param peer_cfg configuration used to find an existing IKE_SA * @return checked out/created IKE_SA */ - ike_sa_t* (*checkout_by_peer) (ike_sa_manager_t* this, - host_t *my_host, host_t* other_host, - identification_t *my_id, - identification_t *other_id); + ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this, + peer_cfg_t *peer_cfg); /** * @brief Check out an IKE_SA a unique ID. |