diff options
Diffstat (limited to 'src/libcharon')
196 files changed, 10098 insertions, 1482 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 21a2b8ee6..90e2bdc6a 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -55,6 +55,7 @@ processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \ processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \ processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \ processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \ +processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ @@ -63,6 +64,8 @@ sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \ sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \ sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \ +sa/authenticators/eap/sim_card.h sa/authenticators/eap/sim_provider.h \ +sa/authenticators/eap/sim_hooks.h \ sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \ sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \ sa/child_sa.c sa/child_sa.h \ @@ -89,8 +92,12 @@ sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \ sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \ sa/tasks/task.c sa/tasks/task.h \ -tnccs/tnccs.c tnccs/tnccs.h \ -tnccs/tnccs_manager.h tnccs/tnccs_manager.c +tnc/tncif.h tnc/tncifimc.h tnc/tncifimv.h tnc/tncifimv.c \ +tnc/imc/imc.h tnc/imc/imc_manager.h \ +tnc/imv/imv.h tnc/imv/imv_manager.h \ +tnc/imv/imv_recommendations.c tnc/imv/imv_recommendations.h \ +tnc/tnccs/tnccs.c tnc/tnccs/tnccs.h \ +tnc/tnccs/tnccs_manager.c tnc/tnccs/tnccs_manager.h # adding the plugin source files diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 1e78c9d79..9a4b28c3a 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -62,6 +62,8 @@ sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \ sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \ sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \ +sa/authenticators/eap/sim_card.h sa/authenticators/eap/sim_provider.h \ +sa/authenticators/eap/sim_hooks.h \ sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \ sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \ sa/child_sa.c sa/child_sa.h \ @@ -221,6 +223,13 @@ if MONOLITHIC endif endif +if USE_EAP_SIM_PCSC + SUBDIRS += plugins/eap_sim_pcsc +if MONOLITHIC + libcharon_la_LIBADD += plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la +endif +endif + if USE_EAP_SIMAKA_SQL SUBDIRS += plugins/eap_simaka_sql if MONOLITHIC @@ -305,6 +314,13 @@ if MONOLITHIC endif endif +if USE_EAP_PEAP + SUBDIRS += plugins/eap_peap +if MONOLITHIC + libcharon_la_LIBADD += plugins/eap_peap/libstrongswan-eap-peap.la +endif +endif + if USE_EAP_TNC SUBDIRS += plugins/eap_tnc if MONOLITHIC @@ -403,6 +419,13 @@ if MONOLITHIC endif endif +if USE_WHITELIST + SUBDIRS += plugins/whitelist +if MONOLITHIC + libcharon_la_LIBADD += plugins/whitelist/libstrongswan-whitelist.la +endif +endif + if USE_LED SUBDIRS += plugins/led if MONOLITHIC @@ -410,6 +433,20 @@ if MONOLITHIC endif endif +if USE_DUPLICHECK + SUBDIRS += plugins/duplicheck +if MONOLITHIC + libcharon_la_LIBADD += plugins/duplicheck/libstrongswan-duplicheck.la +endif +endif + +if USE_COUPLING + SUBDIRS += plugins/coupling +if MONOLITHIC + libcharon_la_LIBADD += plugins/coupling/libstrongswan-coupling.la +endif +endif + if USE_UCI SUBDIRS += plugins/uci if MONOLITHIC diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in index 6ec4c6ca5..70385f306 100644 --- a/src/libcharon/Makefile.in +++ b/src/libcharon/Makefile.in @@ -69,64 +69,74 @@ host_triplet = @host@ @MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_24 = plugins/eap_sim/libstrongswan-eap-sim.la @USE_EAP_SIM_FILE_TRUE@am__append_25 = plugins/eap_sim_file @MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_26 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la -@USE_EAP_SIMAKA_SQL_TRUE@am__append_27 = plugins/eap_simaka_sql -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_28 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la -@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_29 = plugins/eap_simaka_pseudonym -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_30 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la -@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_31 = plugins/eap_simaka_reauth -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_32 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la -@USE_EAP_AKA_TRUE@am__append_33 = plugins/eap_aka -@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_34 = plugins/eap_aka/libstrongswan-eap-aka.la -@USE_EAP_AKA_3GPP2_TRUE@am__append_35 = plugins/eap_aka_3gpp2 -@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_36 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la -@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_37 = $(top_builddir)/src/libsimaka/libsimaka.la -@USE_EAP_MD5_TRUE@am__append_38 = plugins/eap_md5 -@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_39 = plugins/eap_md5/libstrongswan-eap-md5.la -@USE_EAP_GTC_TRUE@am__append_40 = plugins/eap_gtc -@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_41 = plugins/eap_gtc/libstrongswan-eap-gtc.la -@USE_EAP_MSCHAPV2_TRUE@am__append_42 = plugins/eap_mschapv2 -@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_43 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la -@USE_EAP_RADIUS_TRUE@am__append_44 = plugins/eap_radius -@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_45 = plugins/eap_radius/libstrongswan-eap-radius.la -@USE_EAP_TLS_TRUE@am__append_46 = plugins/eap_tls -@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_47 = plugins/eap_tls/libstrongswan-eap-tls.la -@USE_EAP_TTLS_TRUE@am__append_48 = plugins/eap_ttls -@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_49 = plugins/eap_ttls/libstrongswan-eap-ttls.la -@USE_EAP_TNC_TRUE@am__append_50 = plugins/eap_tnc -@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_51 = plugins/eap_tnc/libstrongswan-eap-tnc.la -@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_52 = $(top_builddir)/src/libtls/libtls.la -@USE_TNC_IMC_TRUE@am__append_53 = plugins/tnc_imc -@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_54 = plugins/tnc_imc/libstrongswan-tnc-imc.la -@USE_TNC_IMV_TRUE@am__append_55 = plugins/tnc_imv -@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_56 = plugins/tnc_imv/libstrongswan-tnc-imv.la -@USE_TNCCS_11_TRUE@am__append_57 = plugins/tnccs_11 -@MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_58 = plugins/tnccs_11/libstrongswan-tnccs-11.la -@USE_TNCCS_20_TRUE@am__append_59 = plugins/tnccs_20 -@MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_60 = plugins/tnccs_20/libstrongswan-tnccs-20.la -@USE_TNCCS_DYNAMIC_TRUE@am__append_61 = plugins/tnccs_dynamic -@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_62 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la -@USE_MEDSRV_TRUE@am__append_63 = plugins/medsrv -@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_64 = plugins/medsrv/libstrongswan-medsrv.la -@USE_MEDCLI_TRUE@am__append_65 = plugins/medcli -@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_66 = plugins/medcli/libstrongswan-medcli.la -@USE_NM_TRUE@am__append_67 = plugins/nm -@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_68 = plugins/nm/libstrongswan-nm.la -@USE_DHCP_TRUE@am__append_69 = plugins/dhcp -@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_70 = plugins/dhcp/libstrongswan-dhcp.la -@USE_ANDROID_TRUE@am__append_71 = plugins/android -@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_72 = plugins/android/libstrongswan-android.la -@USE_MAEMO_TRUE@am__append_73 = plugins/maemo -@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_74 = plugins/maemo/libstrongswan-maemo.la -@USE_HA_TRUE@am__append_75 = plugins/ha -@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_76 = plugins/ha/libstrongswan-ha.la -@USE_LED_TRUE@am__append_77 = plugins/led -@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_78 = plugins/led/libstrongswan-led.la -@USE_UCI_TRUE@am__append_79 = plugins/uci -@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_80 = plugins/uci/libstrongswan-uci.la -@USE_ADDRBLOCK_TRUE@am__append_81 = plugins/addrblock -@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_82 = plugins/uci/libstrongswan-addrblock.la -@USE_UNIT_TESTS_TRUE@am__append_83 = plugins/unit_tester -@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_84 = plugins/unit_tester/libstrongswan-unit-tester.la +@USE_EAP_SIM_PCSC_TRUE@am__append_27 = plugins/eap_sim_pcsc +@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_28 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la +@USE_EAP_SIMAKA_SQL_TRUE@am__append_29 = plugins/eap_simaka_sql +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_30 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la +@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_31 = plugins/eap_simaka_pseudonym +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_32 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la +@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_33 = plugins/eap_simaka_reauth +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_34 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la +@USE_EAP_AKA_TRUE@am__append_35 = plugins/eap_aka +@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_36 = plugins/eap_aka/libstrongswan-eap-aka.la +@USE_EAP_AKA_3GPP2_TRUE@am__append_37 = plugins/eap_aka_3gpp2 +@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_38 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la +@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_39 = $(top_builddir)/src/libsimaka/libsimaka.la +@USE_EAP_MD5_TRUE@am__append_40 = plugins/eap_md5 +@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_41 = plugins/eap_md5/libstrongswan-eap-md5.la +@USE_EAP_GTC_TRUE@am__append_42 = plugins/eap_gtc +@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_43 = plugins/eap_gtc/libstrongswan-eap-gtc.la +@USE_EAP_MSCHAPV2_TRUE@am__append_44 = plugins/eap_mschapv2 +@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_45 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la +@USE_EAP_RADIUS_TRUE@am__append_46 = plugins/eap_radius +@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_47 = plugins/eap_radius/libstrongswan-eap-radius.la +@USE_EAP_TLS_TRUE@am__append_48 = plugins/eap_tls +@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_49 = plugins/eap_tls/libstrongswan-eap-tls.la +@USE_EAP_TTLS_TRUE@am__append_50 = plugins/eap_ttls +@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_51 = plugins/eap_ttls/libstrongswan-eap-ttls.la +@USE_EAP_PEAP_TRUE@am__append_52 = plugins/eap_peap +@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_53 = plugins/eap_peap/libstrongswan-eap-peap.la +@USE_EAP_TNC_TRUE@am__append_54 = plugins/eap_tnc +@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_55 = plugins/eap_tnc/libstrongswan-eap-tnc.la +@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_56 = $(top_builddir)/src/libtls/libtls.la +@USE_TNC_IMC_TRUE@am__append_57 = plugins/tnc_imc +@MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE@am__append_58 = plugins/tnc_imc/libstrongswan-tnc-imc.la +@USE_TNC_IMV_TRUE@am__append_59 = plugins/tnc_imv +@MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE@am__append_60 = plugins/tnc_imv/libstrongswan-tnc-imv.la +@USE_TNCCS_11_TRUE@am__append_61 = plugins/tnccs_11 +@MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE@am__append_62 = plugins/tnccs_11/libstrongswan-tnccs-11.la +@USE_TNCCS_20_TRUE@am__append_63 = plugins/tnccs_20 +@MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE@am__append_64 = plugins/tnccs_20/libstrongswan-tnccs-20.la +@USE_TNCCS_DYNAMIC_TRUE@am__append_65 = plugins/tnccs_dynamic +@MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE@am__append_66 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la +@USE_MEDSRV_TRUE@am__append_67 = plugins/medsrv +@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_68 = plugins/medsrv/libstrongswan-medsrv.la +@USE_MEDCLI_TRUE@am__append_69 = plugins/medcli +@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_70 = plugins/medcli/libstrongswan-medcli.la +@USE_NM_TRUE@am__append_71 = plugins/nm +@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_72 = plugins/nm/libstrongswan-nm.la +@USE_DHCP_TRUE@am__append_73 = plugins/dhcp +@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_74 = plugins/dhcp/libstrongswan-dhcp.la +@USE_ANDROID_TRUE@am__append_75 = plugins/android +@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_76 = plugins/android/libstrongswan-android.la +@USE_MAEMO_TRUE@am__append_77 = plugins/maemo +@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_78 = plugins/maemo/libstrongswan-maemo.la +@USE_HA_TRUE@am__append_79 = plugins/ha +@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_80 = plugins/ha/libstrongswan-ha.la +@USE_WHITELIST_TRUE@am__append_81 = plugins/whitelist +@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_82 = plugins/whitelist/libstrongswan-whitelist.la +@USE_LED_TRUE@am__append_83 = plugins/led +@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_84 = plugins/led/libstrongswan-led.la +@USE_DUPLICHECK_TRUE@am__append_85 = plugins/duplicheck +@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_86 = plugins/duplicheck/libstrongswan-duplicheck.la +@USE_COUPLING_TRUE@am__append_87 = plugins/coupling +@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_88 = plugins/coupling/libstrongswan-coupling.la +@USE_UCI_TRUE@am__append_89 = plugins/uci +@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_90 = plugins/uci/libstrongswan-uci.la +@USE_ADDRBLOCK_TRUE@am__append_91 = plugins/addrblock +@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_92 = plugins/uci/libstrongswan-addrblock.la +@USE_UNIT_TESTS_TRUE@am__append_93 = plugins/unit_tester +@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_94 = plugins/unit_tester/libstrongswan-unit-tester.la subdir = src/libcharon DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -176,15 +186,16 @@ libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__append_20) $(am__append_22) $(am__append_24) \ $(am__append_26) $(am__append_28) $(am__append_30) \ $(am__append_32) $(am__append_34) $(am__append_36) \ - $(am__append_37) $(am__append_39) $(am__append_41) \ + $(am__append_38) $(am__append_39) $(am__append_41) \ $(am__append_43) $(am__append_45) $(am__append_47) \ - $(am__append_49) $(am__append_51) $(am__append_52) \ - $(am__append_54) $(am__append_56) $(am__append_58) \ + $(am__append_49) $(am__append_51) $(am__append_53) \ + $(am__append_55) $(am__append_56) $(am__append_58) \ $(am__append_60) $(am__append_62) $(am__append_64) \ $(am__append_66) $(am__append_68) $(am__append_70) \ $(am__append_72) $(am__append_74) $(am__append_76) \ $(am__append_78) $(am__append_80) $(am__append_82) \ - $(am__append_84) + $(am__append_84) $(am__append_86) $(am__append_88) \ + $(am__append_90) $(am__append_92) $(am__append_94) am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ bus/listeners/listener.h bus/listeners/file_logger.c \ bus/listeners/file_logger.h bus/listeners/sys_logger.c \ @@ -270,6 +281,9 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ sa/authenticators/eap/eap_manager.h \ sa/authenticators/eap/sim_manager.c \ sa/authenticators/eap/sim_manager.h \ + sa/authenticators/eap/sim_card.h \ + sa/authenticators/eap/sim_provider.h \ + sa/authenticators/eap/sim_hooks.h \ sa/authenticators/psk_authenticator.c \ sa/authenticators/psk_authenticator.h \ sa/authenticators/pubkey_authenticator.c \ @@ -369,15 +383,17 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \ plugins/socket_raw plugins/socket_dynamic plugins/farp \ plugins/stroke plugins/smp plugins/sql plugins/updown \ plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \ - plugins/eap_simaka_sql plugins/eap_simaka_pseudonym \ - plugins/eap_simaka_reauth plugins/eap_aka \ - plugins/eap_aka_3gpp2 plugins/eap_md5 plugins/eap_gtc \ - plugins/eap_mschapv2 plugins/eap_radius plugins/eap_tls \ - plugins/eap_ttls plugins/eap_tnc plugins/tnc_imc \ - plugins/tnc_imv plugins/tnccs_11 plugins/tnccs_20 \ - plugins/tnccs_dynamic plugins/medsrv plugins/medcli plugins/nm \ - plugins/dhcp plugins/android plugins/maemo plugins/ha \ - plugins/led plugins/uci plugins/addrblock plugins/unit_tester + plugins/eap_sim_pcsc plugins/eap_simaka_sql \ + plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \ + plugins/eap_aka plugins/eap_aka_3gpp2 plugins/eap_md5 \ + plugins/eap_gtc plugins/eap_mschapv2 plugins/eap_radius \ + plugins/eap_tls plugins/eap_ttls plugins/eap_peap \ + plugins/eap_tnc plugins/tnc_imc plugins/tnc_imv \ + plugins/tnccs_11 plugins/tnccs_20 plugins/tnccs_dynamic \ + plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \ + plugins/android plugins/maemo plugins/ha plugins/whitelist \ + plugins/led plugins/duplicheck plugins/coupling plugins/uci \ + plugins/addrblock plugins/unit_tester DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -544,6 +560,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -567,6 +585,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ @@ -660,6 +679,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ sa/authenticators/eap/eap_manager.h \ sa/authenticators/eap/sim_manager.c \ sa/authenticators/eap/sim_manager.h \ + sa/authenticators/eap/sim_card.h \ + sa/authenticators/eap/sim_provider.h \ + sa/authenticators/eap/sim_hooks.h \ sa/authenticators/psk_authenticator.c \ sa/authenticators/psk_authenticator.h \ sa/authenticators/pubkey_authenticator.c \ @@ -706,15 +728,16 @@ libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \ $(am__append_20) $(am__append_22) $(am__append_24) \ $(am__append_26) $(am__append_28) $(am__append_30) \ $(am__append_32) $(am__append_34) $(am__append_36) \ - $(am__append_37) $(am__append_39) $(am__append_41) \ + $(am__append_38) $(am__append_39) $(am__append_41) \ $(am__append_43) $(am__append_45) $(am__append_47) \ - $(am__append_49) $(am__append_51) $(am__append_52) \ - $(am__append_54) $(am__append_56) $(am__append_58) \ + $(am__append_49) $(am__append_51) $(am__append_53) \ + $(am__append_55) $(am__append_56) $(am__append_58) \ $(am__append_60) $(am__append_62) $(am__append_64) \ $(am__append_66) $(am__append_68) $(am__append_70) \ $(am__append_72) $(am__append_74) $(am__append_76) \ $(am__append_78) $(am__append_80) $(am__append_82) \ - $(am__append_84) + $(am__append_84) $(am__append_86) $(am__append_88) \ + $(am__append_90) $(am__append_92) $(am__append_94) EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_5) \ @MONOLITHIC_FALSE@ $(am__append_7) $(am__append_9) \ @@ -724,18 +747,21 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_23) $(am__append_25) \ @MONOLITHIC_FALSE@ $(am__append_27) $(am__append_29) \ @MONOLITHIC_FALSE@ $(am__append_31) $(am__append_33) \ -@MONOLITHIC_FALSE@ $(am__append_35) $(am__append_38) \ +@MONOLITHIC_FALSE@ $(am__append_35) $(am__append_37) \ @MONOLITHIC_FALSE@ $(am__append_40) $(am__append_42) \ @MONOLITHIC_FALSE@ $(am__append_44) $(am__append_46) \ @MONOLITHIC_FALSE@ $(am__append_48) $(am__append_50) \ -@MONOLITHIC_FALSE@ $(am__append_53) $(am__append_55) \ +@MONOLITHIC_FALSE@ $(am__append_52) $(am__append_54) \ @MONOLITHIC_FALSE@ $(am__append_57) $(am__append_59) \ @MONOLITHIC_FALSE@ $(am__append_61) $(am__append_63) \ @MONOLITHIC_FALSE@ $(am__append_65) $(am__append_67) \ @MONOLITHIC_FALSE@ $(am__append_69) $(am__append_71) \ @MONOLITHIC_FALSE@ $(am__append_73) $(am__append_75) \ @MONOLITHIC_FALSE@ $(am__append_77) $(am__append_79) \ -@MONOLITHIC_FALSE@ $(am__append_81) $(am__append_83) +@MONOLITHIC_FALSE@ $(am__append_81) $(am__append_83) \ +@MONOLITHIC_FALSE@ $(am__append_85) $(am__append_87) \ +@MONOLITHIC_FALSE@ $(am__append_89) $(am__append_91) \ +@MONOLITHIC_FALSE@ $(am__append_93) # build optional plugins ######################## @@ -747,18 +773,21 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_23) $(am__append_25) \ @MONOLITHIC_TRUE@ $(am__append_27) $(am__append_29) \ @MONOLITHIC_TRUE@ $(am__append_31) $(am__append_33) \ -@MONOLITHIC_TRUE@ $(am__append_35) $(am__append_38) \ +@MONOLITHIC_TRUE@ $(am__append_35) $(am__append_37) \ @MONOLITHIC_TRUE@ $(am__append_40) $(am__append_42) \ @MONOLITHIC_TRUE@ $(am__append_44) $(am__append_46) \ @MONOLITHIC_TRUE@ $(am__append_48) $(am__append_50) \ -@MONOLITHIC_TRUE@ $(am__append_53) $(am__append_55) \ +@MONOLITHIC_TRUE@ $(am__append_52) $(am__append_54) \ @MONOLITHIC_TRUE@ $(am__append_57) $(am__append_59) \ @MONOLITHIC_TRUE@ $(am__append_61) $(am__append_63) \ @MONOLITHIC_TRUE@ $(am__append_65) $(am__append_67) \ @MONOLITHIC_TRUE@ $(am__append_69) $(am__append_71) \ @MONOLITHIC_TRUE@ $(am__append_73) $(am__append_75) \ @MONOLITHIC_TRUE@ $(am__append_77) $(am__append_79) \ -@MONOLITHIC_TRUE@ $(am__append_81) $(am__append_83) +@MONOLITHIC_TRUE@ $(am__append_81) $(am__append_83) \ +@MONOLITHIC_TRUE@ $(am__append_85) $(am__append_87) \ +@MONOLITHIC_TRUE@ $(am__append_89) $(am__append_91) \ +@MONOLITHIC_TRUE@ $(am__append_93) all: all-recursive .SUFFIXES: diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c index 157436a7d..36d18619a 100644 --- a/src/libcharon/bus/listeners/file_logger.c +++ b/src/libcharon/bus/listeners/file_logger.c @@ -53,11 +53,9 @@ struct private_file_logger_t { bool ike_name; }; -/** - * Implementation of bus_listener_t.log. - */ -static bool log_(private_file_logger_t *this, debug_t group, level_t level, - int thread, ike_sa_t* ike_sa, char *format, va_list args) +METHOD(listener_t, log_, bool, + private_file_logger_t *this, debug_t group, level_t level, int thread, + ike_sa_t* ike_sa, char *format, va_list args) { if (level <= this->levels[group]) { @@ -118,10 +116,8 @@ static bool log_(private_file_logger_t *this, debug_t group, level_t level, return TRUE; } -/** - * Implementation of file_logger_t.set_level. - */ -static void set_level(private_file_logger_t *this, debug_t group, level_t level) +METHOD(file_logger_t, set_level, void, + private_file_logger_t *this, debug_t group, level_t level) { if (group < DBG_ANY) { @@ -136,10 +132,8 @@ static void set_level(private_file_logger_t *this, debug_t group, level_t level) } } -/** - * Implementation of file_logger_t.destroy. - */ -static void destroy(private_file_logger_t *this) +METHOD(file_logger_t, destroy, void, + private_file_logger_t *this) { if (this->out != stdout && this->out != stderr) { @@ -153,18 +147,21 @@ static void destroy(private_file_logger_t *this) */ file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name) { - private_file_logger_t *this = malloc_thing(private_file_logger_t); - - /* public functions */ - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_; - this->public.set_level = (void(*)(file_logger_t*,debug_t,level_t))set_level; - this->public.destroy = (void(*)(file_logger_t*))destroy; - - /* private variables */ - this->out = out; - this->time_format = time_format; - this->ike_name = ike_name; + private_file_logger_t *this; + + INIT(this, + .public = { + .listener = { + .log = _log_, + }, + .set_level = _set_level, + .destroy = _destroy, + }, + .out = out, + .time_format = time_format, + .ike_name = ike_name, + ); + set_level(this, DBG_ANY, LEVEL_SILENT); return &this->public; diff --git a/src/libcharon/bus/listeners/sys_logger.c b/src/libcharon/bus/listeners/sys_logger.c index fa394ba88..c29c9f2e4 100644 --- a/src/libcharon/bus/listeners/sys_logger.c +++ b/src/libcharon/bus/listeners/sys_logger.c @@ -48,19 +48,19 @@ struct private_sys_logger_t { bool ike_name; }; -/** - * Implementation of listener_t.log. - */ -static bool log_(private_sys_logger_t *this, debug_t group, level_t level, - int thread, ike_sa_t* ike_sa, char *format, va_list args) +METHOD(listener_t, log_, bool, + private_sys_logger_t *this, debug_t group, level_t level, int thread, + ike_sa_t* ike_sa, char *format, va_list args) { if (level <= this->levels[group]) { - char buffer[8192], namestr[128] = ""; + char buffer[8192], groupstr[4], namestr[128] = ""; char *current = buffer, *next; /* write in memory buffer first */ vsnprintf(buffer, sizeof(buffer), format, args); + /* cache group name */ + snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group); if (this->ike_name && ike_sa) { @@ -84,8 +84,8 @@ static bool log_(private_sys_logger_t *this, debug_t group, level_t level, { *(next++) = '\0'; } - syslog(this->facility|LOG_INFO, "%.2d[%N]%s %s\n", - thread, debug_names, group, namestr, current); + syslog(this->facility|LOG_INFO, "%.2d[%s]%s %s\n", + thread, groupstr, namestr, current); current = next; } } @@ -93,10 +93,8 @@ static bool log_(private_sys_logger_t *this, debug_t group, level_t level, return TRUE; } -/** - * Implementation of sys_logger_t.set_level. - */ -static void set_level(private_sys_logger_t *this, debug_t group, level_t level) +METHOD(sys_logger_t, set_level, void, + private_sys_logger_t *this, debug_t group, level_t level) { if (group < DBG_ANY) { @@ -111,10 +109,8 @@ static void set_level(private_sys_logger_t *this, debug_t group, level_t level) } } -/** - * Implementation of sys_logger_t.destroy. - */ -static void destroy(private_sys_logger_t *this) +METHOD(sys_logger_t, destroy, void, + private_sys_logger_t *this) { closelog(); free(this); @@ -125,17 +121,20 @@ static void destroy(private_sys_logger_t *this) */ sys_logger_t *sys_logger_create(int facility, bool ike_name) { - private_sys_logger_t *this = malloc_thing(private_sys_logger_t); - - /* public functions */ - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.log = (bool(*)(listener_t*,debug_t,level_t,int,ike_sa_t*,char*,va_list))log_; - this->public.set_level = (void(*)(sys_logger_t*,debug_t,level_t))set_level; - this->public.destroy = (void(*)(sys_logger_t*))destroy; + private_sys_logger_t *this; + + INIT(this, + .public = { + .listener = { + .log = _log_, + }, + .set_level = _set_level, + .destroy = _destroy, + }, + .facility = facility, + .ike_name = ike_name, + ); - /* private variables */ - this->facility = facility; - this->ike_name = ike_name; set_level(this, DBG_ANY, LEVEL_SILENT); return &this->public; diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 86a59bc1b..2251b82dd 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -35,11 +35,6 @@ ENUM(protocol_id_names, PROTO_NONE, PROTO_ESP, "ESP", ); -ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, - "NO_EXT_SEQ", - "EXT_SEQ", -); - typedef struct private_proposal_t private_proposal_t; typedef struct algorithm_t algorithm_t; @@ -549,6 +544,16 @@ static void check_proposal(private_proposal_t *this) free(alg); } } + + if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP) + { + e = this->esns->create_enumerator(this->esns); + if (!e->enumerate(e, &alg)) + { /* ESN not specified, assume not supported */ + add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); + } + e->destroy(e); + } } /** @@ -918,9 +923,5 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs check_proposal(this); - if (protocol == PROTO_AH || protocol == PROTO_ESP) - { - add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); - } return &this->public; } diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h index 97af5b60b..9337518bf 100644 --- a/src/libcharon/config/proposal.h +++ b/src/libcharon/config/proposal.h @@ -51,19 +51,6 @@ enum protocol_id_t { extern enum_name_t *protocol_id_names; /** - * Extended sequence numbers, as in IKEv2 RFC 3.3.2. - */ -enum extended_sequence_numbers_t { - NO_EXT_SEQ_NUMBERS = 0, - EXT_SEQ_NUMBERS = 1 -}; - -/** - * enum strings for extended_sequence_numbers_t. - */ -extern enum_name_t *extended_sequence_numbers_names; - -/** * Stores a set of algorithms used for an SA. * * A proposal stores algorithms for a specific diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 94c64028c..5bc19d11b 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -331,6 +331,8 @@ static status_t terminate_ike(controller_t *this, u_int32_t unique_id, return terminate_ike_execute(&job); } charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job); + /* checkin of the ike_sa happend in the thread that executed the job */ + charon->bus->set_sa(charon->bus, NULL); return job.listener.status; } @@ -417,6 +419,8 @@ static status_t terminate_child(controller_t *this, u_int32_t reqid, return terminate_child_execute(&job); } charon->bus->listen(charon->bus, &job.listener.public, (job_t*)&job); + /* checkin of the ike_sa happend in the thread that executed the job */ + charon->bus->set_sa(charon->bus, NULL); return job.listener.status; } diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index 4f2831e42..796e455a7 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -172,8 +172,10 @@ METHOD(daemon_t, drop_capabilities, bool, .version = _LINUX_CAPABILITY_VERSION_3, #elif defined(_LINUX_CAPABILITY_VERSION_2) .version = _LINUX_CAPABILITY_VERSION_2, -#else +#elif defined(_LINUX_CAPABILITY_VERSION_1) .version = _LINUX_CAPABILITY_VERSION_1, +#else + .version = _LINUX_CAPABILITY_VERSION, #endif }; if (capset(&header, this->caps) != 0) @@ -198,15 +200,17 @@ METHOD(daemon_t, start, void, */ static void print_plugins() { - char buf[512], *plugin; + char buf[512]; int len = 0; enumerator_t *enumerator; + plugin_t *plugin; buf[0] = '\0'; enumerator = lib->plugins->create_plugin_enumerator(lib->plugins); while (len < sizeof(buf) && enumerator->enumerate(enumerator, &plugin)) { - len += snprintf(&buf[len], sizeof(buf)-len, "%s ", plugin); + len += snprintf(&buf[len], sizeof(buf)-len, "%s ", + plugin->get_name(plugin)); } enumerator->destroy(enumerator); DBG1(DBG_DMN, "loaded plugins: %s", buf); diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index dbef340ab..214612fdb 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -45,6 +45,16 @@ #define MAX_DELETE_PAYLOADS 20 /** + * Max number of certificate payloads per IKEv2 Message + */ +#define MAX_CERT_PAYLOADS 8 + +/** + * Max number of Vendor ID payloads per IKEv2 Message + */ +#define MAX_VID_PAYLOADS 20 + +/** * A payload rule defines the rules for a payload * in a specific message rule. It defines if and how * many times a payload must/can occur in a message @@ -104,7 +114,7 @@ static payload_rule_t ike_sa_init_i_rules[] = { {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, {NONCE, 1, 1, FALSE, FALSE}, - {VENDOR_ID, 0, 10, FALSE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, }; /** @@ -131,8 +141,8 @@ static payload_rule_t ike_sa_init_r_rules[] = { {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, {NONCE, 1, 1, FALSE, FALSE}, - {CERTIFICATE_REQUEST, 1, 1, FALSE, FALSE}, - {VENDOR_ID, 0, 10, FALSE, FALSE}, + {CERTIFICATE_REQUEST, 0, 1, FALSE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, }; /** @@ -160,7 +170,7 @@ static payload_rule_t ike_auth_i_rules[] = { {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE}, {AUTHENTICATION, 0, 1, TRUE, TRUE}, {ID_INITIATOR, 0, 1, TRUE, FALSE}, - {CERTIFICATE, 0, 4, TRUE, FALSE}, + {CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE}, {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE}, {ID_RESPONDER, 0, 1, TRUE, FALSE}, #ifdef ME @@ -173,7 +183,7 @@ static payload_rule_t ike_auth_i_rules[] = { {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, #endif /* ME */ {CONFIGURATION, 0, 1, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -213,13 +223,13 @@ static payload_rule_t ike_auth_r_rules[] = { {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, {EXTENSIBLE_AUTHENTICATION, 0, 1, TRUE, TRUE}, {AUTHENTICATION, 0, 1, TRUE, TRUE}, - {CERTIFICATE, 0, 4, TRUE, FALSE}, + {CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE}, {ID_RESPONDER, 0, 1, TRUE, FALSE}, {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE}, {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, {CONFIGURATION, 0, 1, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -256,7 +266,7 @@ static payload_rule_t informational_i_rules[] = { {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {CONFIGURATION, 0, 1, TRUE, FALSE}, {DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -281,7 +291,7 @@ static payload_rule_t informational_r_rules[] = { {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {CONFIGURATION, 0, 1, TRUE, FALSE}, {DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -310,7 +320,7 @@ static payload_rule_t create_child_sa_i_rules[] = { {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, {CONFIGURATION, 0, 1, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -343,7 +353,7 @@ static payload_rule_t create_child_sa_r_rules[] = { {TRAFFIC_SELECTOR_INITIATOR, 0, 1, TRUE, FALSE}, {TRAFFIC_SELECTOR_RESPONDER, 0, 1, TRUE, FALSE}, {CONFIGURATION, 0, 1, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE}, + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; /** @@ -372,7 +382,7 @@ static payload_rule_t me_connect_i_rules[] = { /* payload type min max encr suff */ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, {ID_PEER, 1, 1, TRUE, FALSE}, - {VENDOR_ID, 0, 10, TRUE, FALSE} + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE} }; /** @@ -391,7 +401,7 @@ static payload_order_t me_connect_i_order[] = { static payload_rule_t me_connect_r_rules[] = { /* payload type min max encr suff */ {NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, - {VENDOR_ID, 0, 10, TRUE, FALSE} + {VENDOR_ID, 0, MAX_VID_PAYLOADS, TRUE, FALSE} }; /** diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index 018318a59..57aab1db7 100644 --- a/src/libcharon/plugins/addrblock/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/addrblock/addrblock_plugin.c b/src/libcharon/plugins/addrblock/addrblock_plugin.c index 5fdb36c5c..72c551f0f 100644 --- a/src/libcharon/plugins/addrblock/addrblock_plugin.c +++ b/src/libcharon/plugins/addrblock/addrblock_plugin.c @@ -43,6 +43,12 @@ struct private_addrblock_plugin_t { addrblock_narrow_t *narrower; }; +METHOD(plugin_t, get_name, char*, + private_addrblock_plugin_t *this) +{ + return "addrblock"; +} + METHOD(plugin_t, destroy, void, private_addrblock_plugin_t *this) { @@ -63,6 +69,8 @@ plugin_t *addrblock_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c index 12cf0c941..1b07378f7 100644 --- a/src/libcharon/plugins/addrblock/addrblock_validator.c +++ b/src/libcharon/plugins/addrblock/addrblock_validator.c @@ -88,7 +88,7 @@ static bool check_addrblock(x509_t *subject, x509_t *issuer) METHOD(cert_validator_t, validate, bool, private_addrblock_validator_t *this, certificate_t *subject, - certificate_t *issuer, bool online, int pathlen, bool anchor, + certificate_t *issuer, bool online, u_int pathlen, bool anchor, auth_cfg_t *auth) { if (subject->get_type(subject) == CERT_X509 && @@ -114,7 +114,9 @@ addrblock_validator_t *addrblock_validator_create() INIT(this, .public = { - .validator.validate = _validate, + .validator = { + .validate = _validate, + }, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in index 7d6eb2b9c..08248da12 100644 --- a/src/libcharon/plugins/android/Makefile.in +++ b/src/libcharon/plugins/android/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c index 3d82d8f60..54a7017a1 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android/android_plugin.c @@ -54,11 +54,16 @@ struct private_android_plugin_t { * Service that interacts with the Android Settings frontend */ android_service_t *service; - }; +METHOD(plugin_t, get_name, char*, + private_android_plugin_t *this) +{ + return "android"; +} + METHOD(plugin_t, destroy, void, - private_android_plugin_t *this) + private_android_plugin_t *this) { hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); @@ -81,6 +86,8 @@ plugin_t *android_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/coupling/Makefile.am b/src/libcharon/plugins/coupling/Makefile.am new file mode 100644 index 000000000..642ce820c --- /dev/null +++ b/src/libcharon/plugins/coupling/Makefile.am @@ -0,0 +1,16 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-coupling.la +else +plugin_LTLIBRARIES = libstrongswan-coupling.la +endif + +libstrongswan_coupling_la_SOURCES = coupling_plugin.h coupling_plugin.c \ + coupling_validator.h coupling_validator.c + +libstrongswan_coupling_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in new file mode 100644 index 000000000..a3104e4c0 --- /dev/null +++ b/src/libcharon/plugins/coupling/Makefile.in @@ -0,0 +1,608 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/coupling +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_coupling_la_LIBADD = +am_libstrongswan_coupling_la_OBJECTS = coupling_plugin.lo \ + coupling_validator.lo +libstrongswan_coupling_la_OBJECTS = \ + $(am_libstrongswan_coupling_la_OBJECTS) +libstrongswan_coupling_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_coupling_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_coupling_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_coupling_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_coupling_la_SOURCES) +DIST_SOURCES = $(libstrongswan_coupling_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-coupling.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-coupling.la +libstrongswan_coupling_la_SOURCES = coupling_plugin.h coupling_plugin.c \ + coupling_validator.h coupling_validator.c + +libstrongswan_coupling_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/coupling/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/coupling/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-coupling.la: $(libstrongswan_coupling_la_OBJECTS) $(libstrongswan_coupling_la_DEPENDENCIES) + $(libstrongswan_coupling_la_LINK) $(am_libstrongswan_coupling_la_rpath) $(libstrongswan_coupling_la_OBJECTS) $(libstrongswan_coupling_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coupling_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coupling_validator.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/coupling/coupling_plugin.c b/src/libcharon/plugins/coupling/coupling_plugin.c new file mode 100644 index 000000000..7ccc51db5 --- /dev/null +++ b/src/libcharon/plugins/coupling/coupling_plugin.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "coupling_plugin.h" + +#include "coupling_validator.h" + +#include <daemon.h> + +typedef struct private_coupling_plugin_t private_coupling_plugin_t; + +/** + * private data of coupling plugin + */ +struct private_coupling_plugin_t { + + /** + * implements plugin interface + */ + coupling_plugin_t public; + + /** + * validator controlling couplings + */ + coupling_validator_t *validator; +}; + +METHOD(plugin_t, get_name, char*, + private_coupling_plugin_t *this) +{ + return "coupling"; +} + +METHOD(plugin_t, destroy, void, + private_coupling_plugin_t *this) +{ + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + this->validator->destroy(this->validator); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *coupling_plugin_create() +{ + private_coupling_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .validator = coupling_validator_create(), + ); + + if (!this->validator) + { + free(this); + return NULL; + } + + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/coupling/coupling_plugin.h b/src/libcharon/plugins/coupling/coupling_plugin.h new file mode 100644 index 000000000..645100b45 --- /dev/null +++ b/src/libcharon/plugins/coupling/coupling_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup coupling coupling + * @ingroup cplugins + * + * @defgroup coupling_plugin coupling_plugin + * @{ @ingroup coupling + */ + +#ifndef COUPLING_PLUGIN_H_ +#define COUPLING_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct coupling_plugin_t coupling_plugin_t; + +/** + * Plugin to couple peer certificates permanently to peer authentication. + */ +struct coupling_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** COUPLING_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/coupling/coupling_validator.c b/src/libcharon/plugins/coupling/coupling_validator.c new file mode 100644 index 000000000..06b6f7d86 --- /dev/null +++ b/src/libcharon/plugins/coupling/coupling_validator.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "coupling_validator.h" + +#include <errno.h> +#include <time.h> + +#include <daemon.h> +#include <threading/mutex.h> + +/* buffer size for hex-encoded hash */ +#define MAX_HASH_SIZE (HASH_SIZE_SHA512 * 2 + 1) + +typedef struct private_coupling_validator_t private_coupling_validator_t; + +/** + * Private data of an coupling_validator_t object. + */ +struct private_coupling_validator_t { + + /** + * Public coupling_validator_t interface. + */ + coupling_validator_t public; + + /** + * Mutex + */ + mutex_t *mutex; + + /** + * File with device couplings + */ + FILE *f; + + /** + * Hasher to create hashes + */ + hasher_t *hasher; + + /** + * maximum number of couplings + */ + int max_couplings; +}; + +/** + * Get hash of a certificate + */ +static bool get_cert_hash(private_coupling_validator_t *this, + certificate_t *cert, char *hex) +{ + char buf[MAX_HASH_SIZE]; + chunk_t encoding; + + if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding)) + { + return FALSE; + } + this->hasher->get_hash(this->hasher, encoding, buf); + free(encoding.ptr); + chunk_to_hex(chunk_create(buf, this->hasher->get_hash_size(this->hasher)), + hex, FALSE); + return TRUE; +} + +/** + * Check if we have an entry for a given hash + */ +static bool has_entry(private_coupling_validator_t *this, char *hash) +{ + char line[256]; + int hash_len; + + hash_len = strlen(hash); + rewind(this->f); + + while (fgets(line, sizeof(line), this->f)) + { + if (strlen(line) >= hash_len && + strncaseeq(line, hash, hash_len)) + { + return TRUE; + } + } + return FALSE; +} + +/** + * Get the number of coupling entries we currently have + */ +static int get_number_of_entries(private_coupling_validator_t *this) +{ + char line[256]; + int count = 0; + + rewind(this->f); + + while (fgets(line, sizeof(line), this->f)) + { + /* valid entries start with hex encoded hash */ + if (strchr("1234567890abcdefABCDEF", line[0])) + { + count++; + } + } + return count; +} + +/** + * Add a new entry to the file + */ +static bool add_entry(private_coupling_validator_t *this, char *hash, + identification_t *id) +{ + return fseek(this->f, 0, SEEK_END) == 0 && + fprintf(this->f, "%s %u '%Y'\n", hash, time(NULL), id) > 0; +} + +METHOD(cert_validator_t, validate, bool, + private_coupling_validator_t *this, + certificate_t *subject, certificate_t *issuer, + bool online, u_int pathlen, bool anchor, auth_cfg_t *auth) +{ + bool valid = FALSE; + char hash[MAX_HASH_SIZE]; + + if (pathlen != 0) + { + return TRUE; + } + if (get_cert_hash(this, subject, hash)) + { + this->mutex->lock(this->mutex); + if (has_entry(this, hash)) + { + DBG1(DBG_CFG, "coupled certificate '%Y' found, accepted", + subject->get_subject(subject)); + valid = TRUE; + } + else if (get_number_of_entries(this) < this->max_couplings) + { + if (add_entry(this, hash, subject->get_subject(subject))) + { + DBG1(DBG_CFG, "coupled new certificate '%Y'", + subject->get_subject(subject)); + valid = TRUE; + } + else + { + DBG1(DBG_CFG, "coupling new certificate '%Y' failed", + subject->get_subject(subject)); + } + } + else + { + DBG1(DBG_CFG, "coupling new certificate '%Y' failed, limit of %d " + "couplings reached", subject->get_subject(subject), + this->max_couplings); + } + this->mutex->unlock(this->mutex); + } + return valid; +} + +METHOD(coupling_validator_t, destroy, void, + private_coupling_validator_t *this) +{ + if (this->f) + { + fclose(this->f); + } + DESTROY_IF(this->hasher); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +coupling_validator_t *coupling_validator_create() +{ + private_coupling_validator_t *this; + char *path, *hash; + int i; + struct { + hash_algorithm_t alg; + char *name; + } hash_types[] = { + { HASH_MD5, "md5"}, + { HASH_SHA1, "sha1"}, + { HASH_SHA256, "sha256"}, + { HASH_SHA384, "sha384"}, + { HASH_SHA512, "sha512"}, + }; + + INIT(this, + .public = { + .validator = { + .validate = _validate, + }, + .destroy = _destroy, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .max_couplings = lib->settings->get_int(lib->settings, + "charon.plugins.coupling.max", 1), + ); + + hash = lib->settings->get_str(lib->settings, + "charon.plugins.coupling.hash", "sha1"); + for (i = 0; i < countof(hash_types); i++) + { + if (strcaseeq(hash_types[i].name, hash)) + { + this->hasher = lib->crypto->create_hasher(lib->crypto, + hash_types[i].alg); + break; + } + } + if (!this->hasher) + { + DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash); + destroy(this); + return NULL; + } + + path = lib->settings->get_str(lib->settings, + "charon.plugins.coupling.file", NULL); + if (!path) + { + DBG1(DBG_CFG, "coupling file path unspecified"); + destroy(this); + return NULL; + } + this->f = fopen(path, "a+"); + if (!this->f) + { + DBG1(DBG_CFG, "opening coupling file '%s' failed: %s", + path, strerror(errno)); + destroy(this); + return NULL; + } + setlinebuf(this->f); + return &this->public; +} diff --git a/src/libcharon/plugins/coupling/coupling_validator.h b/src/libcharon/plugins/coupling/coupling_validator.h new file mode 100644 index 000000000..d6b4d3718 --- /dev/null +++ b/src/libcharon/plugins/coupling/coupling_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup coupling_validator coupling_validator + * @{ @ingroup coupling + */ + +#ifndef COUPLING_VALIDATOR_H_ +#define COUPLING_VALIDATOR_H_ + +#include <credentials/cert_validator.h> + +typedef struct coupling_validator_t coupling_validator_t; + +/** + * Validator that couples authenticated certificates permanently. + */ +struct coupling_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a coupling_validator_t. + */ + void (*destroy)(coupling_validator_t *this); +}; + +/** + * Create a coupling_validator instance. + */ +coupling_validator_t *coupling_validator_create(); + +#endif /** COUPLING_VALIDATOR_H_ @}*/ diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index 8046fc052..7853659df 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -241,6 +241,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -264,6 +266,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.c b/src/libcharon/plugins/dhcp/dhcp_plugin.c index fccc99ba5..f8782c2a4 100644 --- a/src/libcharon/plugins/dhcp/dhcp_plugin.c +++ b/src/libcharon/plugins/dhcp/dhcp_plugin.c @@ -44,6 +44,12 @@ struct private_dhcp_plugin_t { dhcp_provider_t *provider; }; +METHOD(plugin_t, get_name, char*, + private_dhcp_plugin_t *this) +{ + return "dhcp"; +} + METHOD(plugin_t, destroy, void, private_dhcp_plugin_t *this) { @@ -64,6 +70,8 @@ plugin_t *dhcp_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c index 8851c1b79..c98d50554 100644 --- a/src/libcharon/plugins/dhcp/dhcp_socket.c +++ b/src/libcharon/plugins/dhcp/dhcp_socket.c @@ -201,6 +201,9 @@ static int prepare_dhcp(private_dhcp_socket_t *this, dhcp->transaction_id = transaction->get_id(transaction); if (chunk_equals(broadcast, this->dst->get_address(this->dst))) { + /* Set broadcast flag to get broadcasted replies, as we actually + * do not own the MAC we request an address for. */ + dhcp->flags = htons(0x8000); /* TODO: send with 0.0.0.0 source address */ } else diff --git a/src/libcharon/plugins/duplicheck/Makefile.am b/src/libcharon/plugins/duplicheck/Makefile.am new file mode 100644 index 000000000..63c91dfab --- /dev/null +++ b/src/libcharon/plugins/duplicheck/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-duplicheck.la +else +plugin_LTLIBRARIES = libstrongswan-duplicheck.la +endif + +libstrongswan_duplicheck_la_SOURCES = duplicheck_plugin.h duplicheck_plugin.c \ + duplicheck_listener.h duplicheck_listener.c \ + duplicheck_notify.h duplicheck_notify.c + +libstrongswan_duplicheck_la_LDFLAGS = -module -avoid-version + +ipsec_PROGRAMS = duplicheck +duplicheck_SOURCES = duplicheck.c diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in new file mode 100644 index 000000000..8cffa2f10 --- /dev/null +++ b/src/libcharon/plugins/duplicheck/Makefile.in @@ -0,0 +1,668 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +ipsec_PROGRAMS = duplicheck$(EXEEXT) +subdir = src/libcharon/plugins/duplicheck +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_duplicheck_la_LIBADD = +am_libstrongswan_duplicheck_la_OBJECTS = duplicheck_plugin.lo \ + duplicheck_listener.lo duplicheck_notify.lo +libstrongswan_duplicheck_la_OBJECTS = \ + $(am_libstrongswan_duplicheck_la_OBJECTS) +libstrongswan_duplicheck_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_duplicheck_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_duplicheck_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_duplicheck_la_rpath = +PROGRAMS = $(ipsec_PROGRAMS) +am_duplicheck_OBJECTS = duplicheck.$(OBJEXT) +duplicheck_OBJECTS = $(am_duplicheck_OBJECTS) +duplicheck_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_duplicheck_la_SOURCES) $(duplicheck_SOURCES) +DIST_SOURCES = $(libstrongswan_duplicheck_la_SOURCES) \ + $(duplicheck_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-duplicheck.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-duplicheck.la +libstrongswan_duplicheck_la_SOURCES = duplicheck_plugin.h duplicheck_plugin.c \ + duplicheck_listener.h duplicheck_listener.c \ + duplicheck_notify.h duplicheck_notify.c + +libstrongswan_duplicheck_la_LDFLAGS = -module -avoid-version +duplicheck_SOURCES = duplicheck.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/duplicheck/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/duplicheck/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-duplicheck.la: $(libstrongswan_duplicheck_la_OBJECTS) $(libstrongswan_duplicheck_la_DEPENDENCIES) + $(libstrongswan_duplicheck_la_LINK) $(am_libstrongswan_duplicheck_la_rpath) $(libstrongswan_duplicheck_la_OBJECTS) $(libstrongswan_duplicheck_la_LIBADD) $(LIBS) +install-ipsecPROGRAMS: $(ipsec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" + @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-ipsecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files + +clean-ipsecPROGRAMS: + @list='$(ipsec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +duplicheck$(EXEEXT): $(duplicheck_OBJECTS) $(duplicheck_DEPENDENCIES) + @rm -f duplicheck$(EXEEXT) + $(LINK) $(duplicheck_OBJECTS) $(duplicheck_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duplicheck.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duplicheck_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duplicheck_notify.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/duplicheck_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-ipsecPROGRAMS install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-ipsecPROGRAMS uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-ipsecPROGRAMS install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-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. +.NOEXPORT: diff --git a/src/libcharon/plugins/duplicheck/duplicheck.c b/src/libcharon/plugins/duplicheck/duplicheck.c new file mode 100644 index 000000000..99731a22b --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stddef.h> +#include <stdio.h> +#include <errno.h> + +#define DUPLICHECK_SOCKET IPSEC_PIDDIR "/charon.dck" + +int main(int argc, char *argv[]) +{ + struct sockaddr_un addr; + char buf[128]; + int fd, len; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, DUPLICHECK_SOCKET); + + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) + { + fprintf(stderr, "opening socket failed: %s\n", strerror(errno)); + return 1; + } + if (connect(fd, (struct sockaddr *)&addr, + offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) + { + fprintf(stderr, "connecting to %s failed: %s\n", + DUPLICHECK_SOCKET, strerror(errno)); + close(fd); + return 1; + } + while (1) + { + len = recv(fd, &buf, sizeof(buf) - 1, 0); + if (len < 0) + { + fprintf(stderr, "reading from socket failed: %s\n", strerror(errno)); + close(fd); + return 1; + } + printf("%.*s\n", len, buf); + } +} diff --git a/src/libcharon/plugins/duplicheck/duplicheck_listener.c b/src/libcharon/plugins/duplicheck/duplicheck_listener.c new file mode 100644 index 000000000..226b2bd4e --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_listener.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "duplicheck_listener.h" + +#include <daemon.h> +#include <threading/mutex.h> +#include <utils/hashtable.h> +#include <encoding/payloads/delete_payload.h> +#include <processing/jobs/delete_ike_sa_job.h> + +typedef struct private_duplicheck_listener_t private_duplicheck_listener_t; + +/** + * Private data of an duplicheck_listener_t object. + */ +struct private_duplicheck_listener_t { + + /** + * Public duplicheck_listener_t interface. + */ + duplicheck_listener_t public; + + /** + * Socket to send notifications to + */ + duplicheck_notify_t *notify; + + /** + * Mutex to lock hashtables + */ + mutex_t *mutex; + + /** + * Hashtable of active IKE_SAs, identification_t => entry_t + */ + hashtable_t *active; + + /** + * Hashtable with active liveness checks, identification_t => entry_t + */ + hashtable_t *checking; +}; + +/** + * Entry for hashtables + */ +typedef struct { + /** peer identity */ + identification_t *id; + /** IKE_SA identifier */ + ike_sa_id_t *sa; +} entry_t; + +/** + * Destroy a hashtable entry + */ +static void entry_destroy(entry_t *this) +{ + this->id->destroy(this->id); + this->sa->destroy(this->sa); + free(this); +} + +/** + * Hashtable hash function + */ +static u_int hash(identification_t *key) +{ + return chunk_hash(key->get_encoding(key)); +} + +/** + * Hashtable equals function + */ +static bool equals(identification_t *a, identification_t *b) +{ + return a->equals(a, b); +} + +METHOD(listener_t, ike_rekey, bool, + private_duplicheck_listener_t *this, ike_sa_t *old, ike_sa_t *new) +{ + identification_t *id; + ike_sa_id_t *sa; + entry_t *entry; + + sa = new->get_id(new); + id = new->get_other_id(new); + + INIT(entry, + .id = id->clone(id), + .sa = sa->clone(sa), + ); + this->mutex->lock(this->mutex); + entry = this->active->put(this->active, entry->id, entry); + this->mutex->unlock(this->mutex); + if (entry) + { + entry_destroy(entry); + } + return TRUE; +} + +METHOD(listener_t, ike_updown, bool, + private_duplicheck_listener_t *this, ike_sa_t *ike_sa, bool up) +{ + identification_t *id; + ike_sa_id_t *sa; + entry_t *entry; + job_t *job; + + sa = ike_sa->get_id(ike_sa); + id = ike_sa->get_other_id(ike_sa); + + if (up) + { + INIT(entry, + .id = id->clone(id), + .sa = sa->clone(sa), + ); + this->mutex->lock(this->mutex); + entry = this->active->put(this->active, entry->id, entry); + this->mutex->unlock(this->mutex); + if (entry) + { + DBG1(DBG_CFG, "detected duplicate IKE_SA for '%Y', " + "triggering delete for old IKE_SA", id); + job = (job_t*)delete_ike_sa_job_create(entry->sa, TRUE); + this->mutex->lock(this->mutex); + entry = this->checking->put(this->checking, entry->id, entry); + this->mutex->unlock(this->mutex); + lib->processor->queue_job(lib->processor, job); + if (entry) + { + entry_destroy(entry); + } + } + } + else + { + this->mutex->lock(this->mutex); + entry = this->checking->remove(this->checking, id); + this->mutex->unlock(this->mutex); + if (entry) + { + DBG1(DBG_CFG, "delete for duplicate IKE_SA '%Y' timed out, " + "keeping new IKE_SA", id); + entry_destroy(entry); + } + else + { + this->mutex->lock(this->mutex); + entry = this->active->remove(this->active, id); + this->mutex->unlock(this->mutex); + if (entry) + { + entry_destroy(entry); + } + } + } + return TRUE; +} + +METHOD(listener_t, message_hook, bool, + private_duplicheck_listener_t *this, ike_sa_t *ike_sa, + message_t *message, bool incoming) +{ + if (incoming && !message->get_request(message)) + { + identification_t *id; + entry_t *entry; + + id = ike_sa->get_other_id(ike_sa); + this->mutex->lock(this->mutex); + entry = this->checking->remove(this->checking, id); + this->mutex->unlock(this->mutex); + if (entry) + { + DBG1(DBG_CFG, "got a response on a duplicate IKE_SA for '%Y', " + "deleting new IKE_SA", id); + entry_destroy(entry); + this->mutex->lock(this->mutex); + entry = this->active->remove(this->active, id); + this->mutex->unlock(this->mutex); + if (entry) + { + lib->processor->queue_job(lib->processor, + (job_t*)delete_ike_sa_job_create(entry->sa, TRUE)); + entry_destroy(entry); + } + this->notify->send(this->notify, id); + } + } + return TRUE; +} + +METHOD(duplicheck_listener_t, destroy, void, + private_duplicheck_listener_t *this) +{ + enumerator_t *enumerator; + identification_t *key; + entry_t *value; + + enumerator = this->active->create_enumerator(this->active); + while (enumerator->enumerate(enumerator, &key, &value)) + { + entry_destroy(value); + } + enumerator->destroy(enumerator); + + enumerator = this->checking->create_enumerator(this->checking); + while (enumerator->enumerate(enumerator, &key, &value)) + { + entry_destroy(value); + } + enumerator->destroy(enumerator); + + this->active->destroy(this->active); + this->checking->destroy(this->checking); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +duplicheck_listener_t *duplicheck_listener_create(duplicheck_notify_t *notify) +{ + private_duplicheck_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_rekey = _ike_rekey, + .ike_updown = _ike_updown, + .message = _message_hook, + }, + .destroy = _destroy, + }, + .notify = notify, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .active = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 32), + .checking = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 2), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/duplicheck/duplicheck_listener.h b/src/libcharon/plugins/duplicheck/duplicheck_listener.h new file mode 100644 index 000000000..7c575dd64 --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_listener.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup duplicheck_listener duplicheck_listener + * @{ @ingroup duplicheck + */ + +#ifndef DUPLICHECK_LISTENER_H_ +#define DUPLICHECK_LISTENER_H_ + +#include "duplicheck_notify.h" + +#include <bus/listeners/listener.h> + +typedef struct duplicheck_listener_t duplicheck_listener_t; + +/** + * Listener checking for duplicates. + */ +struct duplicheck_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a duplicheck_listener_t. + */ + void (*destroy)(duplicheck_listener_t *this); +}; + +/** + * Create a duplicheck_listener instance. + * + * @param notify socket to send notifications to + * @return listener + */ +duplicheck_listener_t *duplicheck_listener_create(duplicheck_notify_t *notify); + +#endif /** DUPLICHECK_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/duplicheck/duplicheck_notify.c b/src/libcharon/plugins/duplicheck/duplicheck_notify.c new file mode 100644 index 000000000..4e7618235 --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_notify.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "duplicheck_notify.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <errno.h> + +#include <daemon.h> +#include <threading/mutex.h> +#include <threading/thread.h> +#include <utils/linked_list.h> +#include <processing/jobs/callback_job.h> + +#define DUPLICHECK_SOCKET IPSEC_PIDDIR "/charon.dck" + +typedef struct private_duplicheck_notify_t private_duplicheck_notify_t; + +/** + * Private data of an duplicheck_notify_t object. + */ +struct private_duplicheck_notify_t { + + /** + * Public duplicheck_notify_t interface. + */ + duplicheck_notify_t public; + + /** + * Callback job dispatching connections + */ + callback_job_t *job; + + /** + * Mutex to lock list + */ + mutex_t *mutex; + + /** + * List of connected sockets + */ + linked_list_t *connected; + + /** + * Socket dispatching connections + */ + int socket; +}; + +/** + * Open duplicheck unix socket + */ +static bool open_socket(private_duplicheck_notify_t *this) +{ + struct sockaddr_un addr; + mode_t old; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, DUPLICHECK_SOCKET); + + this->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (this->socket == -1) + { + DBG1(DBG_CFG, "creating duplicheck socket failed"); + return FALSE; + } + unlink(addr.sun_path); + old = umask(~(S_IRWXU | S_IRWXG)); + if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { + DBG1(DBG_CFG, "binding duplicheck socket failed: %s", strerror(errno)); + close(this->socket); + return FALSE; + } + umask(old); + if (chown(addr.sun_path, charon->uid, charon->gid) != 0) + { + DBG1(DBG_CFG, "changing duplicheck socket permissions failed: %s", + strerror(errno)); + } + if (listen(this->socket, 3) < 0) + { + DBG1(DBG_CFG, "listening on duplicheck socket failed: %s", + strerror(errno)); + close(this->socket); + unlink(addr.sun_path); + return FALSE; + } + return TRUE; +} + +/** + * Accept duplicheck notification connections + */ +static job_requeue_t receive(private_duplicheck_notify_t *this) +{ + struct sockaddr_un addr; + int len = sizeof(addr); + uintptr_t fd; + bool oldstate; + + oldstate = thread_cancelability(TRUE); + fd = accept(this->socket, (struct sockaddr*)&addr, &len); + thread_cancelability(oldstate); + + if (fd != -1) + { + this->mutex->lock(this->mutex); + this->connected->insert_last(this->connected, (void*)fd); + this->mutex->unlock(this->mutex); + } + else + { + DBG1(DBG_CFG, "accepting duplicheck connection failed: %s", + strerror(errno)); + } + return JOB_REQUEUE_FAIR; +} + +METHOD(duplicheck_notify_t, send_, void, + private_duplicheck_notify_t *this, identification_t *id) +{ + char buf[128]; + enumerator_t *enumerator; + uintptr_t fd; + int len; + + len = snprintf(buf, sizeof(buf), "%Y", id); + if (len > 0 && len < sizeof(buf)) + { + this->mutex->lock(this->mutex); + enumerator = this->connected->create_enumerator(this->connected); + while (enumerator->enumerate(enumerator, &fd)) + { + if (send(fd, &buf, len + 1, 0) != len + 1) + { + DBG1(DBG_CFG, "sending duplicheck notify failed: %s", + strerror(errno)); + this->connected->remove_at(this->connected, enumerator); + close(fd); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + } +} + +METHOD(duplicheck_notify_t, destroy, void, + private_duplicheck_notify_t *this) +{ + enumerator_t *enumerator; + uintptr_t fd; + + if (this->job) + { + this->job->cancel(this->job); + } + enumerator = this->connected->create_enumerator(this->connected); + while (enumerator->enumerate(enumerator, &fd)) + { + close(fd); + } + enumerator->destroy(enumerator); + this->connected->destroy(this->connected); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +duplicheck_notify_t *duplicheck_notify_create() +{ + private_duplicheck_notify_t *this; + + INIT(this, + .public = { + .send = _send_, + .destroy = _destroy, + }, + .connected = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + if (!open_socket(this)) + { + destroy(this); + return NULL; + } + this->job = callback_job_create((callback_job_cb_t)receive, + this, NULL, NULL); + lib->processor->queue_job(lib->processor, (job_t*)this->job); + + return &this->public; +} diff --git a/src/libcharon/plugins/duplicheck/duplicheck_notify.h b/src/libcharon/plugins/duplicheck/duplicheck_notify.h new file mode 100644 index 000000000..43dd20cca --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_notify.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup duplicheck_notify duplicheck_notify + * @{ @ingroup duplicheck + */ + +#ifndef DUPLICHECK_NOTIFY_H_ +#define DUPLICHECK_NOTIFY_H_ + +#include <utils/identification.h> + +typedef struct duplicheck_notify_t duplicheck_notify_t; + +/** + * Sends notifications over a unix socket when duplicates are detected. + */ +struct duplicheck_notify_t { + + /** + * Send a notification message if duplicate IKE_SA detected. + * + * @param id identity a duplicate tunnel has been detected + */ + void (*send)(duplicheck_notify_t *this, identification_t *id); + + /** + * Destroy a duplicheck_notify_t. + */ + void (*destroy)(duplicheck_notify_t *this); +}; + +/** + * Create a duplicheck_notify instance. + */ +duplicheck_notify_t *duplicheck_notify_create(); + +#endif /** DUPLICHECK_NOTIFY_H_ @}*/ diff --git a/src/libcharon/plugins/duplicheck/duplicheck_plugin.c b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c new file mode 100644 index 000000000..5bc1a14af --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_plugin.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "duplicheck_plugin.h" + +#include "duplicheck_notify.h" +#include "duplicheck_listener.h" + +#include <daemon.h> + +typedef struct private_duplicheck_plugin_t private_duplicheck_plugin_t; + +/** + * Private data of duplicheck plugin + */ +struct private_duplicheck_plugin_t { + + /** + * Implements plugin interface + */ + duplicheck_plugin_t public; + + /** + * Listener doing duplicate checks + */ + duplicheck_listener_t *listener; + + /** + * Notification sender facility + */ + duplicheck_notify_t *notify; +}; + +METHOD(plugin_t, get_name, char*, + private_duplicheck_plugin_t *this) +{ + return "duplicheck"; +} + +METHOD(plugin_t, destroy, void, + private_duplicheck_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->notify->destroy(this->notify); + this->listener->destroy(this->listener); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *duplicheck_plugin_create() +{ + private_duplicheck_plugin_t *this; + + if (!lib->settings->get_bool(lib->settings, + "charon.plugins.duplicheck.enabled", TRUE)) + { + return NULL; + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .notify = duplicheck_notify_create(), + ); + + if (!this->notify) + { + free(this); + return NULL; + } + this->listener = duplicheck_listener_create(this->notify); + charon->bus->add_listener(charon->bus, &this->listener->listener); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/duplicheck/duplicheck_plugin.h b/src/libcharon/plugins/duplicheck/duplicheck_plugin.h new file mode 100644 index 000000000..3dddf1494 --- /dev/null +++ b/src/libcharon/plugins/duplicheck/duplicheck_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup duplicheck duplicheck + * @ingroup cplugins + * + * @defgroup duplicheck_plugin duplicheck_plugin + * @{ @ingroup duplicheck + */ + +#ifndef DUPLICHECK_PLUGIN_H_ +#define DUPLICHECK_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct duplicheck_plugin_t duplicheck_plugin_t; + +/** + * Advanced duplicate checking using liveness checks. + */ +struct duplicheck_plugin_t { + + /** + * Implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** DUPLICHECK_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index 4a23f9010..666e22957 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c index dfcc69710..df0c4c5b4 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c @@ -54,6 +54,11 @@ struct private_eap_aka_peer_t { identification_t *reauth; /** + * EAP message identifier + */ + u_int8_t identifier; + + /** * MSK */ chunk_t msk; @@ -72,8 +77,7 @@ struct private_eap_aka_peer_t { /** * Create a AKA_CLIENT_ERROR: "Unable to process" */ -static eap_payload_t* create_client_error(private_eap_aka_peer_t *this, - u_int8_t identifier) +static eap_payload_t* create_client_error(private_eap_aka_peer_t *this) { simaka_message_t *message; eap_payload_t *out; @@ -82,7 +86,7 @@ static eap_payload_t* create_client_error(private_eap_aka_peer_t *this, DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, AKA_UNABLE_TO_PROCESS); - message = simaka_message_create(FALSE, identifier, EAP_AKA, + message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_CLIENT_ERROR, this->crypto); encoded = htons(AKA_UNABLE_TO_PROCESS); message->add_attribute(message, AT_CLIENT_ERROR_CODE, @@ -124,7 +128,7 @@ static status_t process_identity(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); enumerator->destroy(enumerator); return NEED_MORE; } @@ -159,7 +163,7 @@ static status_t process_identity(private_eap_aka_peer_t *this, default: break; } - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA, + message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_IDENTITY, this->crypto); if (id.len) { @@ -200,7 +204,7 @@ static status_t process_challenge(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); enumerator->destroy(enumerator); return NEED_MORE; } @@ -212,7 +216,7 @@ static status_t process_challenge(private_eap_aka_peer_t *this, if (!rand.len || !autn.len) { DBG1(DBG_IKE, "received invalid EAP-AKA challenge message"); - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } @@ -258,7 +262,7 @@ static status_t process_challenge(private_eap_aka_peer_t *this, * reading encrypted attributes */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } @@ -285,7 +289,7 @@ static status_t process_challenge(private_eap_aka_peer_t *this, } enumerator->destroy(enumerator); - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA, + message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_CHALLENGE, this->crypto); message->add_attribute(message, AT_RES, chunk_create(res, res_len)); *out = message->generate(message, chunk_empty); @@ -320,7 +324,7 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, { DBG1(DBG_IKE, "received %N, but not expected", simaka_subtype_names, AKA_REAUTHENTICATION); - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } @@ -330,7 +334,7 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, /* verify MAC and parse again with decryption key */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } @@ -351,7 +355,7 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); enumerator->destroy(enumerator); return NEED_MORE; } @@ -363,7 +367,7 @@ static status_t process_reauthentication(private_eap_aka_peer_t *this, if (!nonce.len || !counter.len) { DBG1(DBG_IKE, "EAP-AKA/Request/Reauthentication message incomplete"); - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } @@ -440,38 +444,38 @@ static status_t process_notification(private_eap_aka_peer_t *this, if (success) { /* empty notification reply */ - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_AKA, + message = simaka_message_create(FALSE, this->identifier, EAP_AKA, AKA_NOTIFICATION, this->crypto); *out = message->generate(message, chunk_empty); message->destroy(message); } else { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); } return NEED_MORE; } -/** - * Implementation of eap_method_t.process - */ -static status_t process(private_eap_aka_peer_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process, status_t, + private_eap_aka_peer_t *this, eap_payload_t *in, eap_payload_t **out) { simaka_message_t *message; status_t status; + /* store received EAP message identifier */ + this->identifier = in->get_identifier(in); + message = simaka_message_create_from_payload(in, this->crypto); if (!message) { - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } if (!message->parse(message)) { message->destroy(message); - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); return NEED_MORE; } switch (message->get_subtype(message)) @@ -491,7 +495,7 @@ static status_t process(private_eap_aka_peer_t *this, default: DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N", simaka_subtype_names, message->get_subtype(message)); - *out = create_client_error(this, in->get_identifier(in)); + *out = create_client_error(this); status = NEED_MORE; break; } @@ -499,28 +503,22 @@ static status_t process(private_eap_aka_peer_t *this, return status; } -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_aka_peer_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate, status_t, + private_eap_aka_peer_t *this, eap_payload_t **out) { /* peer never initiates */ return FAILED; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_aka_peer_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_aka_peer_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_AKA; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_aka_peer_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_aka_peer_t *this, chunk_t *msk) { if (this->msk.ptr) { @@ -530,18 +528,26 @@ static status_t get_msk(private_eap_aka_peer_t *this, chunk_t *msk) return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_aka_peer_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_aka_peer_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_aka_peer_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_aka_peer_t *this) { return TRUE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_aka_peer_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_aka_peer_t *this) { this->crypto->destroy(this->crypto); this->permanent->destroy(this->permanent); @@ -557,25 +563,31 @@ static void destroy(private_eap_aka_peer_t *this) eap_aka_peer_t *eap_aka_peer_create(identification_t *server, identification_t *peer) { - private_eap_aka_peer_t *this = malloc_thing(private_eap_aka_peer_t); - - this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.interface.destroy = (void(*)(eap_method_t*))destroy; + private_eap_aka_peer_t *this; + + INIT(this, + .public = { + .interface = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .crypto = simaka_crypto_create(), + ); - this->crypto = simaka_crypto_create(); if (!this->crypto) { free(this); return NULL; } + this->permanent = peer->clone(peer); - this->pseudonym = NULL; - this->reauth = NULL; - this->msk = chunk_empty; return &this->public; } diff --git a/src/libcharon/plugins/eap_aka/eap_aka_plugin.c b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c index f9283393a..394a14b59 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_plugin.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_plugin.c @@ -20,10 +20,14 @@ #include <daemon.h> -/** - * Implementation of plugin_t.destroy - */ -static void destroy(eap_aka_plugin_t *this) +METHOD(plugin_t, get_name, char*, + eap_aka_plugin_t *this) +{ + return "eap-aka"; +} + +METHOD(plugin_t, destroy, void, + eap_aka_plugin_t *this) { charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_aka_server_create); @@ -37,9 +41,15 @@ static void destroy(eap_aka_plugin_t *this) */ plugin_t *eap_aka_plugin_create() { - eap_aka_plugin_t *this = malloc_thing(eap_aka_plugin_t); - - this->plugin.destroy = (void(*)(plugin_t*))destroy; + eap_aka_plugin_t *this; + + INIT(this, + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + ); charon->eap->add_method(charon->eap, EAP_AKA, 0, EAP_SERVER, (eap_constructor_t)eap_aka_server_create); diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c index 9baff3e23..bf0020ad8 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_server.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c @@ -57,7 +57,7 @@ struct private_eap_aka_server_t { identification_t *reauth; /** - * EAP identifier value + * EAP message identifier */ u_int8_t identifier; @@ -251,10 +251,8 @@ static status_t reauthenticate(private_eap_aka_server_t *this, return NEED_MORE; } -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_aka_server_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate, status_t, + private_eap_aka_server_t *this, eap_payload_t **out) { if (this->use_permanent || this->use_pseudonym || this->use_reauth) { @@ -560,11 +558,8 @@ static status_t process_authentication_reject(private_eap_aka_server_t *this, return FAILED; } -/** - * Implementation of eap_method_t.process - */ -static status_t process(private_eap_aka_server_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process, status_t, + private_eap_aka_server_t *this, eap_payload_t *in, eap_payload_t **out) { simaka_message_t *message; status_t status; @@ -609,19 +604,15 @@ static status_t process(private_eap_aka_server_t *this, return status; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_aka_server_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_aka_server_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_AKA; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_aka_server_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_aka_server_t *this, chunk_t *msk) { if (this->msk.ptr) { @@ -631,18 +622,26 @@ static status_t get_msk(private_eap_aka_server_t *this, chunk_t *msk) return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_aka_server_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_aka_server_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_aka_server_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_aka_server_t *this) { return TRUE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_aka_server_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_aka_server_t *this) { this->crypto->destroy(this->crypto); this->permanent->destroy(this->permanent); @@ -662,34 +661,35 @@ static void destroy(private_eap_aka_server_t *this) eap_aka_server_t *eap_aka_server_create(identification_t *server, identification_t *peer) { - private_eap_aka_server_t *this = malloc_thing(private_eap_aka_server_t); - - this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.interface.destroy = (void(*)(eap_method_t*))destroy; + private_eap_aka_server_t *this; + + INIT(this, + .public = { + .interface = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .crypto = simaka_crypto_create(), + ); - this->crypto = simaka_crypto_create(); if (!this->crypto) { free(this); return NULL; } + this->permanent = peer->clone(peer); - this->pseudonym = NULL; - this->reauth = NULL; - this->xres = chunk_empty; - this->rand = chunk_empty; - this->nonce = chunk_empty; - this->msk = chunk_empty; - this->counter = chunk_empty; - this->pending = 0; - this->synchronized = FALSE; this->use_reauth = this->use_pseudonym = this->use_permanent = lib->settings->get_bool(lib->settings, "charon.plugins.eap-aka.request_identity", TRUE); + /* generate a non-zero identifier */ do { this->identifier = random(); diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index ad1ae1906..1fe86a2bb 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c index 626e83311..ef5f62e34 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_plugin.c @@ -48,10 +48,14 @@ struct private_eap_aka_3gpp2_t { eap_aka_3gpp2_functions_t *functions; }; -/** - * Implementation of eap_aka_3gpp2_t.destroy. - */ -static void destroy(private_eap_aka_3gpp2_t *this) +METHOD(plugin_t, get_name, char*, + private_eap_aka_3gpp2_t *this) +{ + return "eap-aka-3gpp2"; +} + +METHOD(plugin_t, destroy, void, + private_eap_aka_3gpp2_t *this) { charon->sim->remove_card(charon->sim, &this->card->card); charon->sim->remove_provider(charon->sim, &this->provider->provider); @@ -66,11 +70,19 @@ static void destroy(private_eap_aka_3gpp2_t *this) */ plugin_t *eap_aka_3gpp2_plugin_create() { - private_eap_aka_3gpp2_t *this = malloc_thing(private_eap_aka_3gpp2_t); + private_eap_aka_3gpp2_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .functions = eap_aka_3gpp2_functions_create(), + ); - this->functions = eap_aka_3gpp2_functions_create(); if (!this->functions) { free(this); diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 142a35e50..4f555a982 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -242,6 +242,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -265,6 +267,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c index f641ad13a..c3ab07de0 100644 --- a/src/libcharon/plugins/eap_gtc/eap_gtc.c +++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c @@ -70,10 +70,8 @@ struct eap_gtc_header_t { u_int8_t data[]; } __attribute__((__packed__)); -/** - * Implementation of eap_method_t.initiate for the peer - */ -static status_t initiate_peer(private_eap_gtc_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate_peer, status_t, + private_eap_gtc_t *this, eap_payload_t **out) { /* peer never initiates */ return FAILED; @@ -136,10 +134,8 @@ static bool authenticate(char *service, char *user, char *password) return ret == PAM_SUCCESS; } -/** - * Implementation of eap_method_t.initiate for the server - */ -static status_t initiate_server(private_eap_gtc_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate_server, status_t, + private_eap_gtc_t *this, eap_payload_t **out) { eap_gtc_header_t *req; size_t len; @@ -157,11 +153,8 @@ static status_t initiate_server(private_eap_gtc_t *this, eap_payload_t **out) return NEED_MORE; } -/** - * Implementation of eap_method_t.process for the peer - */ -static status_t process_peer(private_eap_gtc_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process_peer, status_t, + private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out) { eap_gtc_header_t *res; shared_key_t *shared; @@ -181,10 +174,11 @@ static status_t process_peer(private_eap_gtc_t *this, /* TODO: According to the draft we should "SASLprep" password, RFC4013. */ + this->identifier = in->get_identifier(in); res = alloca(sizeof(eap_gtc_header_t) + len); res->length = htons(sizeof(eap_gtc_header_t) + len); res->code = EAP_RESPONSE; - res->identifier = in->get_identifier(in); + res->identifier = this->identifier; res->type = EAP_GTC; memcpy(res->data, key.ptr, len); @@ -195,11 +189,8 @@ static status_t process_peer(private_eap_gtc_t *this, return NEED_MORE; } -/** - * Implementation of eap_method_t.process for the server - */ -static status_t process_server(private_eap_gtc_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process_server, status_t, + private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out) { chunk_t data, encoding; char *user, *password, *service, *pos; @@ -236,35 +227,39 @@ static status_t process_server(private_eap_gtc_t *this, return SUCCESS; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_gtc_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_gtc_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_GTC; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_gtc_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_gtc_t *this, chunk_t *msk) { return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_gtc_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_gtc_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_gtc_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_gtc_t *this) { return FALSE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_gtc_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_gtc_t *this) { this->peer->destroy(this->peer); this->server->destroy(this->server); @@ -277,19 +272,22 @@ static void destroy(private_eap_gtc_t *this) static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server, identification_t *peer) { - private_eap_gtc_t *this = malloc_thing(private_eap_gtc_t); - - this->public.eap_method_interface.initiate = NULL; - this->public.eap_method_interface.process = NULL; - 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->clone(peer); - this->server = server->clone(server); - this->identifier = 0; + private_eap_gtc_t *this; + + INIT(this, + .public = { + .eap_method_interface = { + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .peer = peer->clone(peer), + .server = server->clone(server), + ); return this; } @@ -301,8 +299,8 @@ eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *pee { private_eap_gtc_t *this = eap_gtc_create_generic(server, peer); - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server; + this->public.eap_method_interface.initiate = _initiate_server; + this->public.eap_method_interface.process = _process_server; /* generate a non-zero identifier */ do { @@ -319,8 +317,8 @@ eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer) { private_eap_gtc_t *this = eap_gtc_create_generic(server, peer); - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer; + this->public.eap_method_interface.initiate = _initiate_peer; + this->public.eap_method_interface.process = _process_peer; return &this->public; } diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c index 91ba84b3d..c40ce60eb 100644 --- a/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c +++ b/src/libcharon/plugins/eap_gtc/eap_gtc_plugin.c @@ -22,10 +22,14 @@ /* missing in cababilities.h */ #define CAP_AUDIT_WRITE 29 -/** - * Implementation of plugin_t.destroy - */ -static void destroy(eap_gtc_plugin_t *this) +METHOD(plugin_t, get_name, char*, + eap_gtc_plugin_t *this) +{ + return "eap-gtc"; +} + +METHOD(plugin_t, destroy, void, + eap_gtc_plugin_t *this) { charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_gtc_create_server); @@ -39,9 +43,15 @@ static void destroy(eap_gtc_plugin_t *this) */ plugin_t *eap_gtc_plugin_create() { - eap_gtc_plugin_t *this = malloc_thing(eap_gtc_plugin_t); + eap_gtc_plugin_t *this; - this->plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + ); /* required for PAM authentication */ charon->keep_cap(charon, CAP_AUDIT_WRITE); diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index 5c1e07ade..9dc4602ff 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_identity/eap_identity.c b/src/libcharon/plugins/eap_identity/eap_identity.c index 03066b2f8..6ecde065c 100644 --- a/src/libcharon/plugins/eap_identity/eap_identity.c +++ b/src/libcharon/plugins/eap_identity/eap_identity.c @@ -39,6 +39,11 @@ struct private_eap_identity_t { * received identity chunk */ chunk_t identity; + + /** + * EAP identifier + */ + u_int8_t identifier; }; typedef struct eap_identity_header_t eap_identity_header_t; @@ -68,10 +73,13 @@ METHOD(eap_method_t, process_peer, status_t, id = this->peer->get_encoding(this->peer); len = sizeof(eap_identity_header_t) + id.len; - + if (in) + { + this->identifier = in->get_identifier(in); + } hdr = alloca(len); hdr->code = EAP_RESPONSE; - hdr->identifier = in ? in->get_identifier(in) : 0; + hdr->identifier = this->identifier; hdr->length = htons(len); hdr->type = EAP_IDENTITY; memcpy(hdr->data, id.ptr, id.len); @@ -106,7 +114,7 @@ METHOD(eap_method_t, initiate_server, status_t, eap_identity_header_t hdr; hdr.code = EAP_REQUEST; - hdr.identifier = 0; + hdr.identifier = this->identifier; hdr.length = htons(sizeof(eap_identity_header_t)); hdr.type = EAP_IDENTITY; @@ -133,6 +141,18 @@ METHOD(eap_method_t, get_msk, status_t, return FAILED; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_identity_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_identity_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + METHOD(eap_method_t, is_mutual, bool, private_eap_identity_t *this) { @@ -163,6 +183,8 @@ eap_identity_t *eap_identity_create_peer(identification_t *server, .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, @@ -189,6 +211,8 @@ eap_identity_t *eap_identity_create_server(identification_t *server, .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/eap_identity/eap_identity_plugin.c b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c index 079c27909..3297416b2 100644 --- a/src/libcharon/plugins/eap_identity/eap_identity_plugin.c +++ b/src/libcharon/plugins/eap_identity/eap_identity_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + eap_identity_plugin_t *this) +{ + return "eap-identity"; +} + METHOD(plugin_t, destroy, void, eap_identity_plugin_t *this) { @@ -37,6 +43,8 @@ plugin_t *eap_identity_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index 4e01d96cc..e828fbc3e 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -242,6 +242,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -265,6 +267,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c index f70754abb..b0a234527 100644 --- a/src/libcharon/plugins/eap_md5/eap_md5.c +++ b/src/libcharon/plugins/eap_md5/eap_md5.c @@ -147,12 +147,12 @@ METHOD(eap_method_t, process_peer, status_t, this->identifier = in->get_identifier(in); data = in->get_data(in); - this->challenge = chunk_clone(chunk_skip(data, 6)); - if (data.len < 6 || this->challenge.len < *(data.ptr + 5)) + if (data.len < 6 || data.ptr[5] + 6 > data.len) { DBG1(DBG_IKE, "received invalid EAP-MD5 message"); return FAILED; } + this->challenge = chunk_clone(chunk_create(data.ptr + 6, data.ptr[5])); if (hash_challenge(this, &response, this->peer, this->server) != SUCCESS) { return FAILED; @@ -176,7 +176,9 @@ METHOD(eap_method_t, process_server, status_t, chunk_t response, expected; chunk_t data; - if (this->identifier != in->get_identifier(in)) + data = in->get_data(in); + if (this->identifier != in->get_identifier(in) || + data.len < 6 || data.ptr[5] + 6 > data.len) { DBG1(DBG_IKE, "received invalid EAP-MD5 message"); return FAILED; @@ -185,9 +187,7 @@ METHOD(eap_method_t, process_server, status_t, { return FAILED; } - data = in->get_data(in); - response = chunk_skip(data, 6); - + response = chunk_create(data.ptr + 6, data.ptr[5]); if (response.len < expected.len || !memeq(response.ptr, expected.ptr, expected.len)) { @@ -218,6 +218,18 @@ METHOD(eap_method_t, is_mutual, bool, return FALSE; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_md5_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_md5_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + METHOD(eap_method_t, destroy, void, private_eap_md5_t *this) { @@ -242,6 +254,8 @@ eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *pee .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/eap_md5/eap_md5_plugin.c b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c index 39a6f5731..fe5ae51bf 100644 --- a/src/libcharon/plugins/eap_md5/eap_md5_plugin.c +++ b/src/libcharon/plugins/eap_md5/eap_md5_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + eap_md5_plugin_t *this) +{ + return "eap-md5"; +} + METHOD(plugin_t, destroy, void, eap_md5_plugin_t *this) { @@ -37,6 +43,8 @@ plugin_t *eap_md5_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index 495ccf441..4986fdce3 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c index 4f39c8608..1dd94f6fb 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c @@ -560,19 +560,15 @@ static void set_ms_length(eap_mschapv2_header_t *eap, u_int16_t len) memcpy(&eap->ms_length, &len, sizeof(u_int16_t)); } -/** - * Implementation of eap_method_t.initiate for the peer - */ -static status_t initiate_peer(private_eap_mschapv2_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate_peer, status_t, + private_eap_mschapv2_t *this, eap_payload_t **out) { /* peer never initiates */ return FAILED; } -/** - * Implementation of eap_method_t.initiate for the server - */ -static status_t initiate_server(private_eap_mschapv2_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate_server, status_t, + private_eap_mschapv2_t *this, eap_payload_t **out) { rng_t *rng; eap_mschapv2_header_t *eap; @@ -904,11 +900,8 @@ error: return status; } -/** - * Implementation of eap_method_t.process for the peer - */ -static status_t process_peer(private_eap_mschapv2_t *this, eap_payload_t *in, - eap_payload_t **out) +METHOD(eap_method_t, process_peer, status_t, + private_eap_mschapv2_t *this, eap_payload_t *in, eap_payload_t **out) { chunk_t data; eap_mschapv2_header_t *eap; @@ -1091,11 +1084,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this, return process_server_retry(this, out); } -/** - * Implementation of eap_method_t.process for the server - */ -static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in, - eap_payload_t **out) +METHOD(eap_method_t, process_server, status_t, + private_eap_mschapv2_t *this, eap_payload_t *in, eap_payload_t **out) { eap_mschapv2_header_t *eap; chunk_t data; @@ -1140,19 +1130,15 @@ static status_t process_server(private_eap_mschapv2_t *this, eap_payload_t *in, return FAILED; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_mschapv2_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_mschapv2_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_MSCHAPV2; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_mschapv2_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_mschapv2_t *this, chunk_t *msk) { if (this->msk.ptr) { @@ -1162,18 +1148,26 @@ static status_t get_msk(private_eap_mschapv2_t *this, chunk_t *msk) return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_mschapv2_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_mschapv2_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_mschapv2_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_mschapv2_t *this) { return FALSE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_mschapv2_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_mschapv2_t *this) { this->peer->destroy(this->peer); this->server->destroy(this->server); @@ -1189,25 +1183,22 @@ static void destroy(private_eap_mschapv2_t *this) */ static private_eap_mschapv2_t *eap_mschapv2_create_generic(identification_t *server, identification_t *peer) { - private_eap_mschapv2_t *this = malloc_thing(private_eap_mschapv2_t); - - this->public.eap_method_interface.initiate = NULL; - this->public.eap_method_interface.process = NULL; - 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->clone(peer); - this->server = server->clone(server); - this->challenge = chunk_empty; - this->nt_response = chunk_empty; - this->auth_response = chunk_empty; - this->msk = chunk_empty; - this->identifier = 0; - this->mschapv2id = 0; - this->retries = 0; + private_eap_mschapv2_t *this; + + INIT(this, + .public = { + .eap_method_interface = { + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .peer = peer->clone(peer), + .server = server->clone(server), + ); return this; } @@ -1219,8 +1210,8 @@ eap_mschapv2_t *eap_mschapv2_create_server(identification_t *server, identificat { private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer); - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*, eap_payload_t**))process_server; + this->public.eap_method_interface.initiate = _initiate_server; + this->public.eap_method_interface.process = _process_server; /* generate a non-zero identifier */ do @@ -1240,8 +1231,8 @@ eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identificatio { private_eap_mschapv2_t *this = eap_mschapv2_create_generic(server, peer); - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*, eap_payload_t**))process_peer; + this->public.eap_method_interface.initiate = _initiate_peer; + this->public.eap_method_interface.process = _process_peer; return &this->public; } diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c index a7b41ddbf..e809b14b6 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2_plugin.c @@ -19,10 +19,14 @@ #include <daemon.h> -/** - * Implementation of plugin_t.destroy - */ -static void destroy(eap_mschapv2_plugin_t *this) +METHOD(plugin_t, get_name, char*, + eap_mschapv2_plugin_t *this) +{ + return "eap-mschapv2"; +} + +METHOD(plugin_t, destroy, void, + eap_mschapv2_plugin_t *this) { charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_mschapv2_create_server); @@ -36,9 +40,15 @@ static void destroy(eap_mschapv2_plugin_t *this) */ plugin_t *eap_mschapv2_plugin_create() { - eap_mschapv2_plugin_t *this = malloc_thing(eap_mschapv2_plugin_t); - - this->plugin.destroy = (void(*)(plugin_t*))destroy; + eap_mschapv2_plugin_t *this; + + INIT(this, + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + ); charon->eap->add_method(charon->eap, EAP_MSCHAPV2, 0, EAP_SERVER, (eap_constructor_t)eap_mschapv2_create_server); diff --git a/src/libcharon/plugins/eap_peap/Makefile.am b/src/libcharon/plugins/eap_peap/Makefile.am new file mode 100644 index 000000000..81f2575c7 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-eap-peap.la +else +plugin_LTLIBRARIES = libstrongswan-eap-peap.la +libstrongswan_eap_peap_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +endif + +libstrongswan_eap_peap_la_SOURCES = \ + eap_peap_plugin.h eap_peap_plugin.c \ + eap_peap.h eap_peap.c \ + eap_peap_peer.h eap_peap_peer.c \ + eap_peap_server.h eap_peap_server.c \ + eap_peap_avp.h eap_peap_avp.c + +libstrongswan_eap_peap_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in new file mode 100644 index 000000000..0ed4a3dcf --- /dev/null +++ b/src/libcharon/plugins/eap_peap/Makefile.in @@ -0,0 +1,617 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/eap_peap +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +@MONOLITHIC_FALSE@libstrongswan_eap_peap_la_DEPENDENCIES = \ +@MONOLITHIC_FALSE@ $(top_builddir)/src/libtls/libtls.la +am_libstrongswan_eap_peap_la_OBJECTS = eap_peap_plugin.lo eap_peap.lo \ + eap_peap_peer.lo eap_peap_server.lo eap_peap_avp.lo +libstrongswan_eap_peap_la_OBJECTS = \ + $(am_libstrongswan_eap_peap_la_OBJECTS) +libstrongswan_eap_peap_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_eap_peap_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_eap_peap_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_eap_peap_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_eap_peap_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eap_peap_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon -I$(top_srcdir)/src/libtls + +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-peap.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-peap.la +@MONOLITHIC_FALSE@libstrongswan_eap_peap_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libstrongswan_eap_peap_la_SOURCES = \ + eap_peap_plugin.h eap_peap_plugin.c \ + eap_peap.h eap_peap.c \ + eap_peap_peer.h eap_peap_peer.c \ + eap_peap_server.h eap_peap_server.c \ + eap_peap_avp.h eap_peap_avp.c + +libstrongswan_eap_peap_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_peap/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/eap_peap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-eap-peap.la: $(libstrongswan_eap_peap_la_OBJECTS) $(libstrongswan_eap_peap_la_DEPENDENCIES) + $(libstrongswan_eap_peap_la_LINK) $(am_libstrongswan_eap_peap_la_rpath) $(libstrongswan_eap_peap_la_OBJECTS) $(libstrongswan_eap_peap_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_peap.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_peap_avp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_peap_peer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_peap_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_peap_server.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/eap_peap/eap_peap.c b/src/libcharon/plugins/eap_peap/eap_peap.c new file mode 100644 index 000000000..5bae0fa9b --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2010 Martin Willi, revosec AG + * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_peap.h" +#include "eap_peap_peer.h" +#include "eap_peap_server.h" + +#include <tls_eap.h> + +#include <daemon.h> +#include <library.h> + +typedef struct private_eap_peap_t private_eap_peap_t; + +/** + * Private data of an eap_peap_t object. + */ +struct private_eap_peap_t { + + /** + * Public interface. + */ + eap_peap_t public; + + /** + * TLS stack, wrapped by EAP helper + */ + tls_eap_t *tls_eap; +}; + +/** Maximum number of EAP-PEAP messages/fragments allowed */ +#define MAX_MESSAGE_COUNT 32 +/** Default size of a EAP-PEAP fragment */ +#define MAX_FRAGMENT_LEN 1024 + +METHOD(eap_method_t, initiate, status_t, + private_eap_peap_t *this, eap_payload_t **out) +{ + chunk_t data; + + if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE) + { + *out = eap_payload_create_data(data); + free(data.ptr); + return NEED_MORE; + } + return FAILED; +} + +METHOD(eap_method_t, process, status_t, + private_eap_peap_t *this, eap_payload_t *in, eap_payload_t **out) +{ + status_t status; + chunk_t data; + + data = in->get_data(in); + status = this->tls_eap->process(this->tls_eap, data, &data); + if (status == NEED_MORE) + { + *out = eap_payload_create_data(data); + free(data.ptr); + } + return status; +} + +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_peap_t *this, u_int32_t *vendor) +{ + *vendor = 0; + return EAP_PEAP; +} + +METHOD(eap_method_t, get_msk, status_t, + private_eap_peap_t *this, chunk_t *msk) +{ + *msk = this->tls_eap->get_msk(this->tls_eap); + if (msk->len) + { + return SUCCESS; + } + return FAILED; +} + +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_peap_t *this) +{ + return this->tls_eap->get_identifier(this->tls_eap); +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_peap_t *this, u_int8_t identifier) +{ + this->tls_eap->set_identifier(this->tls_eap, identifier); +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_peap_t *this) +{ + return TRUE; +} + +METHOD(eap_method_t, destroy, void, + private_eap_peap_t *this) +{ + this->tls_eap->destroy(this->tls_eap); + free(this); +} + +/** + * Create an empty private eap_peap_t object + */ +static private_eap_peap_t *eap_peap_create_empty(void) +{ + private_eap_peap_t *this; + + INIT(this, + .public = { + .eap_method = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + ); + return this; +} + +/** + * Generic private constructor + */ +static eap_peap_t *eap_peap_create(private_eap_peap_t * this, + identification_t *server, + identification_t *peer, bool is_server, + tls_application_t *application) +{ + size_t frag_size; + int max_msg_count; + bool include_length; + tls_t *tls; + + if (is_server && !lib->settings->get_bool(lib->settings, + "charon.plugins.eap-peap.request_peer_auth", FALSE)) + { + peer = NULL; + } + frag_size = lib->settings->get_int(lib->settings, + "charon.plugins.eap-peap.fragment_size", MAX_FRAGMENT_LEN); + max_msg_count = lib->settings->get_int(lib->settings, + "charon.plugins.eap-peap.max_message_count", MAX_MESSAGE_COUNT); + include_length = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-peap.include_length", FALSE); + tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_PEAP, application); + this->tls_eap = tls_eap_create(EAP_PEAP, tls, frag_size, max_msg_count, + include_length); + if (!this->tls_eap) + { + application->destroy(application); + free(this); + return NULL; + } + return &this->public; +} + +eap_peap_t *eap_peap_create_server(identification_t *server, + identification_t *peer) +{ + private_eap_peap_t *eap_peap; + eap_method_t *eap_method; + eap_peap_server_t *eap_peap_server; + tls_application_t *application; + + /* the tunneled application needs a reference to the outer EAP-PEAP method */ + eap_peap = eap_peap_create_empty(); + eap_method = &eap_peap->public.eap_method; + eap_peap_server = eap_peap_server_create(server, peer, eap_method); + application = &eap_peap_server->application; + + return eap_peap_create(eap_peap, server, peer, TRUE, application); +} + +eap_peap_t *eap_peap_create_peer(identification_t *server, + identification_t *peer) +{ + private_eap_peap_t *eap_peap; + eap_method_t *eap_method; + eap_peap_peer_t *eap_peap_peer; + tls_application_t *application; + + /* the tunneled application needs a reference to the outer EAP-PEAP method */ + eap_peap = eap_peap_create_empty(); + eap_method = &eap_peap->public.eap_method; + eap_peap_peer = eap_peap_peer_create(server, peer, eap_method); + application = &eap_peap_peer->application; + + return eap_peap_create(eap_peap, server, peer, FALSE, application); +} diff --git a/src/libcharon/plugins/eap_peap/eap_peap.h b/src/libcharon/plugins/eap_peap/eap_peap.h new file mode 100644 index 000000000..f47bad561 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_peap_i eap_peap + * @{ @ingroup eap_peap + */ + +#ifndef EAP_PEAP_H_ +#define EAP_PEAP_H_ + +typedef struct eap_peap_t eap_peap_t; + +#include <sa/authenticators/eap/eap_method.h> + +/** + * Implementation of eap_method_t using EAP-PEAP. + */ +struct eap_peap_t { + + /** + * Implements eap_method_t interface. + */ + eap_method_t eap_method; +}; + +/** + * Creates the EAP method EAP-PEAP acting as server. + * + * @param server ID of the EAP server + * @param peer ID of the EAP client + * @return eap_peap_t object + */ +eap_peap_t *eap_peap_create_server(identification_t *server, + identification_t *peer); + +/** + * Creates the EAP method EAP-PEAP acting as peer. + * + * @param server ID of the EAP server + * @param peer ID of the EAP client + * @return eap_peap_t object + */ +eap_peap_t *eap_peap_create_peer(identification_t *server, + identification_t *peer); + +#endif /** EAP_PEAP_H_ @}*/ diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.c b/src/libcharon/plugins/eap_peap/eap_peap_avp.c new file mode 100644 index 000000000..06e5222d9 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_peap_avp.h" + +#include <eap/eap.h> +#include <debug.h> + +/** + * Microsoft Success and Failure Result AVPs + */ +static const chunk_t MS_AVP_Success = chunk_from_chars( + 0x80, 0x03, 0x00, 0x02, 0x00, 0x01); +static const chunk_t MS_AVP_Failure = chunk_from_chars( + 0x80, 0x03, 0x00, 0x02, 0x00, 0x02); + +typedef struct private_eap_peap_avp_t private_eap_peap_avp_t; + +/** + * Private data of an eap_peap_avp_t object. + */ +struct private_eap_peap_avp_t { + + /** + * Public eap_peap_avp_t interface. + */ + eap_peap_avp_t public; + + /** + * EAP server or peer + */ + bool is_server; +}; + +METHOD(eap_peap_avp_t, build, void, + private_eap_peap_avp_t *this, tls_writer_t *writer, chunk_t data) +{ + u_int8_t code; + eap_packet_t *pkt; + chunk_t avp_data; + + pkt = (eap_packet_t*)data.ptr; + + if (pkt->code == EAP_SUCCESS || pkt->code == EAP_FAILURE) + { + code = (this->is_server) ? EAP_REQUEST : EAP_RESPONSE; + writer->write_uint8(writer, code); + writer->write_uint8(writer, pkt->identifier); + writer->write_uint16(writer, 11); + writer->write_uint8(writer, EAP_MSTLV); + avp_data = (pkt->code == EAP_SUCCESS) ? MS_AVP_Success : MS_AVP_Failure; + } + else + { + avp_data = chunk_skip(data, 4); + } + writer->write_data(writer, avp_data); +} + +METHOD(eap_peap_avp_t, process, status_t, + private_eap_peap_avp_t* this, tls_reader_t *reader, chunk_t *data, + u_int8_t identifier) +{ + u_int8_t code; + u_int16_t len; + eap_packet_t *pkt; + chunk_t avp_data; + + code = (this->is_server) ? EAP_RESPONSE : EAP_REQUEST; + len = reader->remaining(reader); + if (!reader->read_data(reader, len, &avp_data)) + { + return FAILED; + } + pkt = (eap_packet_t*)avp_data.ptr; + + if (len > 4 && pkt->code == code && untoh16(&pkt->length) == len) + { + if (len == 5 && pkt->type == EAP_IDENTITY) + { + DBG2(DBG_IKE, "uncompressed EAP Identity request"); + *data = chunk_clone(avp_data); + return SUCCESS; + } + else if (len == 11 && pkt->type == EAP_MSTLV) + { + if (memeq(&pkt->data, MS_AVP_Success.ptr, MS_AVP_Success.len)) + { + DBG2(DBG_IKE, "MS Success Result AVP"); + code = EAP_SUCCESS; + } + else if (memeq(&pkt->data, MS_AVP_Failure.ptr, MS_AVP_Failure.len)) + { + DBG2(DBG_IKE, "MS Failure Result AVP"); + code = EAP_FAILURE; + } + else + { + DBG1(DBG_IKE, "unknown MS AVP message"); + return FAILED; + } + identifier = pkt->identifier; + len = 0; + } + } + + *data = chunk_alloc(4 + len); + pkt = (eap_packet_t*)data->ptr; + pkt->code = code; + pkt->identifier = identifier; + htoun16(&pkt->length, data->len); + memcpy(data->ptr + 4, avp_data.ptr, len); + + return SUCCESS; +} + +METHOD(eap_peap_avp_t, destroy, void, + private_eap_peap_avp_t *this) +{ + free(this); +} + +/** + * See header + */ +eap_peap_avp_t *eap_peap_avp_create(bool is_server) +{ + private_eap_peap_avp_t *this; + + INIT(this, + .public= { + .process = _process, + .build = _build, + .destroy = _destroy, + }, + .is_server = is_server, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.h b/src/libcharon/plugins/eap_peap/eap_peap_avp.h new file mode 100644 index 000000000..db22f0f8f --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_peap_avp eap_peap_avp + * @{ @ingroup eap_peap + */ + +#ifndef EAP_PEAP_AVP_H_ +#define EAP_PEAP_AVP_H_ + +typedef struct eap_peap_avp_t eap_peap_avp_t; + +#include <library.h> + +#include <tls_reader.h> +#include <tls_writer.h> + +/** + * EAP-PEAP Attribute-Value Pair (AVP) handler. + */ +struct eap_peap_avp_t { + + /** + * Process received EAP-PEAP Message AVP. + * + * @param reader TLS data buffer + * @param data received EAP Message + * @param identifier EAP-PEAP message identifier + * @return + * - SUCCESS if AVP processing succeeded + * - FAILED if AVP processing failed + * - NEED_MORE if another invocation of process/build needed + */ + status_t (*process)(eap_peap_avp_t *this, tls_reader_t *reader, + chunk_t *data, u_int8_t identifier); + + /** + * Build EAP-PEAP Message AVP to send out. + * + * @param writer TLS data buffer to write to + * @param data EAP Message to send + */ + void (*build)(eap_peap_avp_t *this, tls_writer_t *writer, chunk_t data); + + /** + * Destroy a eap_peap_application_t. + */ + void (*destroy)(eap_peap_avp_t *this); +}; + +/** + * Create an eap_peap_avp instance. + * + * @param is_server TRUE iv eap server, FALSE if eap peer + */ +eap_peap_avp_t *eap_peap_avp_create(bool is_server); + +#endif /** EAP_PEAP_AVP_H_ @}*/ diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.c b/src/libcharon/plugins/eap_peap/eap_peap_peer.c new file mode 100644 index 000000000..ca2af4fee --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_peap_peer.h" +#include "eap_peap_avp.h" + +#include <debug.h> +#include <daemon.h> + +typedef struct private_eap_peap_peer_t private_eap_peap_peer_t; + +/** + * Private data of an eap_peap_peer_t object. + */ +struct private_eap_peap_peer_t { + + /** + * Public eap_peap_peer_t interface. + */ + eap_peap_peer_t public; + + /** + * Server identity + */ + identification_t *server; + + /** + * Peer identity + */ + identification_t *peer; + + /** + * Outer phase 1 EAP method + */ + eap_method_t *ph1_method; + + /** + * Current phase 2 EAP method + */ + eap_method_t *ph2_method; + + /** + * Pending outbound EAP message + */ + eap_payload_t *out; + + /** + * AVP handler + */ + eap_peap_avp_t *avp; +}; + +METHOD(tls_application_t, process, status_t, + private_eap_peap_peer_t *this, tls_reader_t *reader) +{ + chunk_t data = chunk_empty; + status_t status; + payload_t *payload; + eap_payload_t *in; + eap_code_t code; + eap_type_t type, received_type; + u_int32_t vendor, received_vendor; + + status = this->avp->process(this->avp, reader, &data, + this->ph1_method->get_identifier(this->ph1_method)); + switch (status) + { + case SUCCESS: + break; + case NEED_MORE: + return NEED_MORE; + case FAILED: + default: + return FAILED; + } + + in = eap_payload_create_data(data); + DBG3(DBG_IKE, "%B", &data); + chunk_free(&data); + payload = (payload_t*)in; + + if (payload->verify(payload) != SUCCESS) + { + in->destroy(in); + return FAILED; + } + + code = in->get_code(in); + if (code == EAP_REQUEST || code == EAP_RESPONSE) + { + received_type = in->get_type(in, &received_vendor); + DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N/%N]", + eap_code_short_names, code, + eap_type_short_names, received_type); + if (code != EAP_REQUEST) + { + DBG1(DBG_IKE, "%N expected", eap_code_names, EAP_REQUEST); + in->destroy(in); + return FAILED; + } + } + else + { + DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]", + eap_code_short_names, code); + this->out = eap_payload_create_code(code, in->get_identifier(in)); + in->destroy(in); + return NEED_MORE; + } + + /* yet another phase2 authentication? */ + if (this->ph2_method) + { + type = this->ph2_method->get_type(this->ph2_method, &vendor); + + if (type != received_type || vendor != received_vendor) + { + this->ph2_method->destroy(this->ph2_method); + this->ph2_method = NULL; + } + } + + if (this->ph2_method == NULL) + { + if (received_vendor) + { + DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d " + "(id 0x%02X", received_type, received_vendor, + in->get_identifier(in)); + } + else + { + DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", + eap_type_names, received_type, in->get_identifier(in)); + } + this->ph2_method = charon->eap->create_instance(charon->eap, + received_type, received_vendor, + EAP_PEER, this->server, this->peer); + if (!this->ph2_method) + { + DBG1(DBG_IKE, "EAP method not supported"); + this->out = eap_payload_create_nak(in->get_identifier(in)); + in->destroy(in); + return NEED_MORE; + } + type = this->ph2_method->get_type(this->ph2_method, &vendor); + } + + status = this->ph2_method->process(this->ph2_method, in, &this->out); + in->destroy(in); + + switch (status) + { + case SUCCESS: + this->ph2_method->destroy(this->ph2_method); + this->ph2_method = NULL; + /* fall through to NEED_MORE */ + case NEED_MORE: + return NEED_MORE; + case FAILED: + default: + if (vendor) + { + DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", + type, vendor); + } + else + { + DBG1(DBG_IKE, "%N method failed", eap_type_names, type); + } + return FAILED; + } +} + +METHOD(tls_application_t, build, status_t, + private_eap_peap_peer_t *this, tls_writer_t *writer) +{ + chunk_t data; + eap_code_t code; + eap_type_t type; + u_int32_t vendor; + + if (this->out) + { + code = this->out->get_code(this->out); + type = this->out->get_type(this->out, &vendor); + if (code == EAP_REQUEST || code == EAP_RESPONSE) + { + DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N/%N]", + eap_code_short_names, code, eap_type_short_names, type); + } + else + { + DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N]", + eap_code_short_names, code); + } + + /* get the raw EAP message data */ + data = this->out->get_data(this->out); + DBG3(DBG_IKE, "%B", &data); + this->avp->build(this->avp, writer, data); + + this->out->destroy(this->out); + this->out = NULL; + } + return INVALID_STATE; +} + +METHOD(tls_application_t, destroy, void, + private_eap_peap_peer_t *this) +{ + this->server->destroy(this->server); + this->peer->destroy(this->peer); + DESTROY_IF(this->ph2_method); + DESTROY_IF(this->out); + this->avp->destroy(this->avp); + free(this); +} + +/** + * See header + */ +eap_peap_peer_t *eap_peap_peer_create(identification_t *server, + identification_t *peer, + eap_method_t *eap_method) +{ + private_eap_peap_peer_t *this; + + INIT(this, + .public = { + .application = { + .process = _process, + .build = _build, + .destroy = _destroy, + }, + }, + .server = server->clone(server), + .peer = peer->clone(peer), + .ph1_method = eap_method, + .avp = eap_peap_avp_create(FALSE), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_peap/eap_peap_peer.h b/src/libcharon/plugins/eap_peap/eap_peap_peer.h new file mode 100644 index 000000000..a87544209 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_peer.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_peap_peer eap_peap_peer + * @{ @ingroup eap_peap + */ + +#ifndef EAP_PEAP_PEER_H_ +#define EAP_PEAP_PEER_H_ + +typedef struct eap_peap_peer_t eap_peap_peer_t; + +#include "tls_application.h" + +#include <library.h> +#include <sa/authenticators/eap/eap_method.h> + +/** + * TLS application data handler as peer. + */ +struct eap_peap_peer_t { + + /** + * Implements the TLS application data handler. + */ + tls_application_t application; +}; + +/** + * Create an eap_peap_peer instance. + */ +eap_peap_peer_t *eap_peap_peer_create(identification_t *server, + identification_t *peer, + eap_method_t *eap_method); + +#endif /** EAP_PEAP_PEER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_peap/eap_peap_plugin.c b/src/libcharon/plugins/eap_peap/eap_peap_plugin.c new file mode 100644 index 000000000..bac5f2d3e --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_plugin.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_peap_plugin.h" + +#include "eap_peap.h" + +#include <daemon.h> + +METHOD(plugin_t, get_name, char*, + eap_peap_plugin_t *this) +{ + return "eap-peap"; +} + +METHOD(plugin_t, destroy, void, + eap_peap_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_peap_create_server); + charon->eap->remove_method(charon->eap, + (eap_constructor_t)eap_peap_create_peer); + free(this); +} + +/* + * see header file + */ +plugin_t *eap_peap_plugin_create() +{ + eap_peap_plugin_t *this; + + INIT(this, + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + ); + + charon->eap->add_method(charon->eap, EAP_PEAP, 0, EAP_SERVER, + (eap_constructor_t)eap_peap_create_server); + charon->eap->add_method(charon->eap, EAP_PEAP, 0, EAP_PEER, + (eap_constructor_t)eap_peap_create_peer); + + return &this->plugin; +} diff --git a/src/libcharon/plugins/eap_peap/eap_peap_plugin.h b/src/libcharon/plugins/eap_peap/eap_peap_plugin.h new file mode 100644 index 000000000..75bb504e1 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_peap eap_peap + * @ingroup cplugins + * + * @defgroup eap_peap_plugin eap_peap_plugin + * @{ @ingroup eap_peap + */ + +#ifndef EAP_PEAP_PLUGIN_H_ +#define EAP_PEAP_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_peap_plugin_t eap_peap_plugin_t; + +/** + * EAP-PEAP plugin + */ +struct eap_peap_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a eap_peap_plugin instance. + */ +plugin_t *eap_peap_plugin_create(); + +#endif /** EAP_PEAP_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c new file mode 100644 index 000000000..3fabc3575 --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_peap_server.h" +#include "eap_peap_avp.h" + +#include <debug.h> +#include <daemon.h> + +typedef struct private_eap_peap_server_t private_eap_peap_server_t; + +/** + * Private data of an eap_peap_server_t object. + */ +struct private_eap_peap_server_t { + + /** + * Public eap_peap_server_t interface. + */ + eap_peap_server_t public; + + /** + * Server identity + */ + identification_t *server; + + /** + * Peer identity + */ + identification_t *peer; + + /** + * Current EAP-PEAP phase2 state + */ + bool start_phase2; + + /** + * Current EAP-PEAP phase2 TNC state + */ + bool start_phase2_tnc; + + /** + * Starts phase 2 with EAP Identity request + */ + bool start_phase2_id; + + /** + * Final EAP-PEAP phase2 result + */ + eap_code_t phase2_result; + + /** + * Outer phase 1 EAP method + */ + eap_method_t *ph1_method; + + /** + * Current phase 2 EAP method + */ + eap_method_t *ph2_method; + + /** + * Pending outbound EAP message + */ + eap_payload_t *out; + + /** + * AVP handler + */ + eap_peap_avp_t *avp; +}; + +/** + * Start EAP client authentication protocol + */ +static status_t start_phase2_auth(private_eap_peap_server_t *this) +{ + char *eap_type_str; + eap_type_t type; + + eap_type_str = lib->settings->get_str(lib->settings, + "charon.plugins.eap-peap.phase2_method", "mschapv2"); + type = eap_type_from_string(eap_type_str); + if (type == 0) + { + DBG1(DBG_IKE, "unrecognized phase2 method \"%s\"", eap_type_str); + return FAILED; + } + DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type); + this->ph2_method = charon->eap->create_instance(charon->eap, type, 0, + EAP_SERVER, this->server, this->peer); + if (this->ph2_method == NULL) + { + DBG1(DBG_IKE, "%N method not available", eap_type_names, type); + return FAILED; + } + + /* synchronize EAP message identifiers of inner protocol with outer */ + this->ph2_method->set_identifier(this->ph2_method, + this->ph1_method->get_identifier(this->ph1_method) + 1); + + if (this->ph2_method->initiate(this->ph2_method, &this->out) == NEED_MORE) + { + return NEED_MORE; + } + else + { + DBG1(DBG_IKE, "%N method failed", eap_type_names, type); + return FAILED; + } +} + +/** + * If configured, start EAP-TNC protocol + */ +static status_t start_phase2_tnc(private_eap_peap_server_t *this) +{ + if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings, + "charon.plugins.eap-peap.phase2_tnc", FALSE)) + { + DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC); + this->ph2_method = charon->eap->create_instance(charon->eap, EAP_TNC, + 0, EAP_SERVER, this->server, this->peer); + if (this->ph2_method == NULL) + { + DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC); + return FAILED; + } + this->start_phase2_tnc = FALSE; + + /* synchronize EAP message identifiers of inner protocol with outer */ + this->ph2_method->set_identifier(this->ph2_method, + this->ph1_method->get_identifier(this->ph1_method) + 1); + + if (this->ph2_method->initiate(this->ph2_method, &this->out) == NEED_MORE) + { + return NEED_MORE; + } + else + { + DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_TNC); + return FAILED; + } + } + return SUCCESS; +} + +METHOD(tls_application_t, process, status_t, + private_eap_peap_server_t *this, tls_reader_t *reader) +{ + chunk_t data = chunk_empty; + status_t status; + payload_t *payload; + eap_payload_t *in; + eap_code_t code; + eap_type_t type = EAP_NAK, received_type; + u_int32_t vendor, received_vendor; + + status = this->avp->process(this->avp, reader, &data, + this->ph1_method->get_identifier(this->ph1_method)); + switch (status) + { + case SUCCESS: + break; + case NEED_MORE: + return NEED_MORE; + case FAILED: + default: + return FAILED; + } + + in = eap_payload_create_data(data); + DBG3(DBG_IKE, "%B", &data); + chunk_free(&data); + payload = (payload_t*)in; + + if (payload->verify(payload) != SUCCESS) + { + in->destroy(in); + return FAILED; + } + + code = in->get_code(in); + if (code == EAP_REQUEST || code == EAP_RESPONSE) + { + received_type = in->get_type(in, &received_vendor); + DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N/%N]", + eap_code_short_names, code, + eap_type_short_names, received_type); + if (code != EAP_RESPONSE) + { + DBG1(DBG_IKE, "%N expected", eap_code_names, EAP_RESPONSE); + in->destroy(in); + return FAILED; + } + } + else + { + DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]", + eap_code_short_names, code); + + /* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */ + return (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) ? + start_phase2_tnc(this) : FAILED; + } + + if (this->ph2_method) + { + type = this->ph2_method->get_type(this->ph2_method, &vendor); + + if (type != received_type || vendor != received_vendor) + { + if (received_vendor == 0 && received_type == EAP_NAK) + { + DBG1(DBG_IKE, "peer does not support %N", eap_type_names, type); + } + else + { + DBG1(DBG_IKE, "received invalid EAP response"); + } + in->destroy(in); + return FAILED; + } + } + + if (!received_vendor && received_type == EAP_IDENTITY) + { + chunk_t eap_id; + + if (this->ph2_method == NULL) + { + /* Received an EAP Identity response without a matching request */ + this->ph2_method = charon->eap->create_instance(charon->eap, + EAP_IDENTITY, 0, EAP_SERVER, + this->server, this->peer); + if (this->ph2_method == NULL) + { + DBG1(DBG_IKE, "%N method not available", + eap_type_names, EAP_IDENTITY); + return FAILED; + } + } + + if (this->ph2_method->process(this->ph2_method, in, &this->out) != SUCCESS) + { + + DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_IDENTITY); + return FAILED; + } + + if (this->ph2_method->get_msk(this->ph2_method, &eap_id) == SUCCESS) + { + this->peer->destroy(this->peer); + this->peer = identification_create_from_data(eap_id); + DBG1(DBG_IKE, "received EAP identity '%Y'", this->peer); + } + + in->destroy(in); + this->ph2_method->destroy(this->ph2_method); + this->ph2_method = NULL; + + /* Start Phase 2 of EAP-PEAP authentication */ + if (lib->settings->get_bool(lib->settings, + "charon.plugins.eap-peap.request_peer_auth", FALSE)) + { + return start_phase2_tnc(this); + } + else + { + return start_phase2_auth(this); + } + } + + if (this->ph2_method == 0) + { + DBG1(DBG_IKE, "no %N phase2 method installed", eap_type_names, EAP_PEAP); + in->destroy(in); + return FAILED; + } + + status = this->ph2_method->process(this->ph2_method, in, &this->out); + in->destroy(in); + + switch (status) + { + case SUCCESS: + DBG1(DBG_IKE, "%N phase2 authentication of '%Y' with %N successful", + eap_type_names, EAP_PEAP, this->peer, + eap_type_names, type); + this->ph2_method->destroy(this->ph2_method); + this->ph2_method = NULL; + + /* EAP-PEAP requires the sending of an inner EAP_SUCCESS message */ + this->phase2_result = EAP_SUCCESS; + this->out = eap_payload_create_code(this->phase2_result, 1 + + this->ph1_method->get_identifier(this->ph1_method)); + return NEED_MORE; + case NEED_MORE: + break; + case FAILED: + default: + if (vendor) + { + DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", + type, vendor); + } + else + { + DBG1(DBG_IKE, "%N method failed", eap_type_names, type); + } + /* EAP-PEAP requires the sending of an inner EAP_FAILURE message */ + this->phase2_result = EAP_FAILURE; + this->out = eap_payload_create_code(this->phase2_result, 1 + + this->ph1_method->get_identifier(this->ph1_method)); + return NEED_MORE; + } + return status; +} + +METHOD(tls_application_t, build, status_t, + private_eap_peap_server_t *this, tls_writer_t *writer) +{ + chunk_t data; + eap_code_t code; + eap_type_t type; + u_int32_t vendor; + + if (this->ph2_method == NULL && this->start_phase2 && this->start_phase2_id) + { + /* + * Start Phase 2 with an EAP Identity request either piggybacked right + * onto the TLS Finished payload or delayed after the reception of an + * empty EAP Acknowledge message. + */ + this->ph2_method = charon->eap->create_instance(charon->eap, EAP_IDENTITY, + 0, EAP_SERVER, this->server, this->peer); + if (this->ph2_method == NULL) + { + DBG1(DBG_IKE, "%N method not available", + eap_type_names, EAP_IDENTITY); + return FAILED; + } + + /* synchronize EAP message identifiers of inner protocol with outer */ + this->ph2_method->set_identifier(this->ph2_method, + this->ph1_method->get_identifier(this->ph1_method)); + + this->ph2_method->initiate(this->ph2_method, &this->out); + this->start_phase2 = FALSE; + } + + this->start_phase2_id = TRUE; + + if (this->out) + { + code = this->out->get_code(this->out); + type = this->out->get_type(this->out, &vendor); + if (code == EAP_REQUEST || code == EAP_RESPONSE) + { + DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N/%N]", + eap_code_short_names, code, eap_type_short_names, type); + } + else + { + DBG1(DBG_IKE, "sending tunneled EAP-PEAP AVP [EAP/%N]", + eap_code_short_names, code); + } + + /* get the raw EAP message data */ + data = this->out->get_data(this->out); + DBG3(DBG_IKE, "%B", &data); + this->avp->build(this->avp, writer, data); + + this->out->destroy(this->out); + this->out = NULL; + } + return INVALID_STATE; +} + +METHOD(tls_application_t, destroy, void, + private_eap_peap_server_t *this) +{ + this->server->destroy(this->server); + this->peer->destroy(this->peer); + DESTROY_IF(this->ph2_method); + DESTROY_IF(this->out); + this->avp->destroy(this->avp); + free(this); +} + +/** + * See header + */ +eap_peap_server_t *eap_peap_server_create(identification_t *server, + identification_t *peer, + eap_method_t *eap_method) +{ + private_eap_peap_server_t *this; + + INIT(this, + .public = { + .application = { + .process = _process, + .build = _build, + .destroy = _destroy, + }, + }, + .server = server->clone(server), + .peer = peer->clone(peer), + .ph1_method = eap_method, + .start_phase2 = TRUE, + .start_phase2_tnc = TRUE, + .start_phase2_id = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-peap.phase2_piggyback", FALSE), + .phase2_result = EAP_FAILURE, + .avp = eap_peap_avp_create(TRUE), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.h b/src/libcharon/plugins/eap_peap/eap_peap_server.h new file mode 100644 index 000000000..93141d62b --- /dev/null +++ b/src/libcharon/plugins/eap_peap/eap_peap_server.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011 HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_peap_server eap_peap_server + * @{ @ingroup eap_peap + */ + +#ifndef EAP_PEAP_SERVER_H_ +#define EAP_PEAP_SERVER_H_ + +typedef struct eap_peap_server_t eap_peap_server_t; + +#include "tls_application.h" + +#include <library.h> +#include <sa/authenticators/eap/eap_method.h> + +/** + * TLS application data handler as server. + */ +struct eap_peap_server_t { + + /** + * Implements the TLS application data handler. + */ + tls_application_t application; +}; + +/** + * Create an eap_peap_server instance. + */ +eap_peap_server_t *eap_peap_server_create(identification_t *server, + identification_t *peer, + eap_method_t *eap_method); + +#endif /** EAP_PEAP_SERVER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 99084e2c1..740c64055 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index 157034fe5..dfe0e2e09 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -55,6 +55,11 @@ struct private_eap_radius_t { u_int32_t vendor; /** + * EAP message identifier + */ + u_int8_t identifier; + + /** * RADIUS client instance */ radius_client_t *client; @@ -107,7 +112,7 @@ static void add_eap_identity(private_eap_radius_t *this, hdr = alloca(len); hdr->code = EAP_RESPONSE; - hdr->identifier = 0; + hdr->identifier = this->identifier; hdr->length = htons(len); hdr->type = EAP_IDENTITY; memcpy(hdr->data, prefix.ptr, prefix.len); @@ -139,9 +144,12 @@ static bool radius2ike(private_eap_radius_t *this, if (message.len) { *out = payload = eap_payload_create_data(message); - free(message.ptr); + /* apply EAP method selected by RADIUS server */ this->type = payload->get_type(payload, &this->vendor); + + DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &message); + free(message.ptr); return TRUE; } return FALSE; @@ -284,6 +292,8 @@ METHOD(eap_method_t, process, status_t, request = radius_message_create_request(); request->add(request, RAT_USER_NAME, this->peer->get_encoding(this->peer)); data = in->get_data(in); + DBG3(DBG_IKE, "%N payload %B", eap_type_names, this->type, &data); + /* fragment data suitable for RADIUS (not more than 253 bytes) */ while (data.len > 253) { @@ -351,6 +361,18 @@ METHOD(eap_method_t, get_msk, status_t, return FAILED; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_radius_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_radius_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + METHOD(eap_method_t, is_mutual, bool, private_eap_radius_t *this) { @@ -388,6 +410,8 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index 1c24d77d5..c218bd48b 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -20,6 +20,7 @@ #include "radius_server.h" #include <daemon.h> +#include <threading/rwlock.h> /** * Default RADIUS server port, when not configured @@ -42,6 +43,11 @@ struct private_eap_radius_plugin_t { * List of RADIUS servers */ linked_list_t *servers; + + /** + * Lock for server list + */ + rwlock_t *lock; }; /** @@ -49,20 +55,10 @@ struct private_eap_radius_plugin_t { */ static private_eap_radius_plugin_t *instance = NULL; -METHOD(plugin_t, destroy, void, - private_eap_radius_plugin_t *this) -{ - charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create); - this->servers->destroy_offset(this->servers, - offsetof(radius_server_t, destroy)); - free(this); - instance = NULL; -} - /** * Load RADIUS servers from configuration */ -static bool load_servers(private_eap_radius_plugin_t *this) +static void load_servers(private_eap_radius_plugin_t *this) { enumerator_t *enumerator; radius_server_t *server; @@ -78,7 +74,7 @@ static bool load_servers(private_eap_radius_plugin_t *this) if (!secret) { DBG1(DBG_CFG, "no RADUIS secret defined"); - return FALSE; + return; } nas_identifier = lib->settings->get_str(lib->settings, "charon.plugins.eap-radius.nas_identifier", "strongSwan"); @@ -86,15 +82,15 @@ static bool load_servers(private_eap_radius_plugin_t *this) "charon.plugins.eap-radius.port", RADIUS_PORT); sockets = lib->settings->get_int(lib->settings, "charon.plugins.eap-radius.sockets", 1); - server = radius_server_create(address, port, nas_identifier, + server = radius_server_create(address, address, port, nas_identifier, secret, sockets, 0); if (!server) { DBG1(DBG_CFG, "no RADUIS server defined"); - return FALSE; + return; } this->servers->insert_last(this->servers, server); - return TRUE; + return; } enumerator = lib->settings->create_section_enumerator(lib->settings, @@ -124,7 +120,7 @@ static bool load_servers(private_eap_radius_plugin_t *this) "charon.plugins.eap-radius.servers.%s.sockets", 1, section); preference = lib->settings->get_int(lib->settings, "charon.plugins.eap-radius.servers.%s.preference", 0, section); - server = radius_server_create(address, port, nas_identifier, + server = radius_server_create(section, address, port, nas_identifier, secret, sockets, preference); if (!server) { @@ -135,14 +131,40 @@ static bool load_servers(private_eap_radius_plugin_t *this) } enumerator->destroy(enumerator); - if (this->servers->get_count(this->servers) == 0) - { - DBG1(DBG_CFG, "no valid RADIUS server configuration found"); - return FALSE; - } + DBG1(DBG_CFG, "loaded %d RADIUS server configuration%s", + this->servers->get_count(this->servers), + this->servers->get_count(this->servers) == 1 ? "" : "s"); +} + +METHOD(plugin_t, get_name, char*, + private_eap_radius_plugin_t *this) +{ + return "eap-radius"; +} + +METHOD(plugin_t, reload, bool, + private_eap_radius_plugin_t *this) +{ + this->lock->write_lock(this->lock); + this->servers->destroy_offset(this->servers, + offsetof(radius_server_t, destroy)); + this->servers = linked_list_create(); + load_servers(this); + this->lock->unlock(this->lock); return TRUE; } +METHOD(plugin_t, destroy, void, + private_eap_radius_plugin_t *this) +{ + charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create); + this->servers->destroy_offset(this->servers, + offsetof(radius_server_t, destroy)); + this->lock->destroy(this->lock); + free(this); + instance = NULL; +} + /* * see header file */ @@ -153,17 +175,17 @@ plugin_t *eap_radius_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = _reload, .destroy = _destroy, }, }, .servers = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), ); - if (!load_servers(this)) - { - destroy(this); - return NULL; - } + load_servers(this); + charon->eap->add_method(charon->eap, EAP_RADIUS, 0, EAP_SERVER, (eap_constructor_t)eap_radius_create); @@ -179,7 +201,10 @@ enumerator_t *eap_radius_create_server_enumerator() { if (instance) { - return instance->servers->create_enumerator(instance->servers); + instance->lock->read_lock(instance->lock); + return enumerator_create_cleaner( + instance->servers->create_enumerator(instance->servers), + (void*)instance->lock->unlock, instance->lock); } return enumerator_create_empty(); } diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c index 232b9135e..245308e59 100644 --- a/src/libcharon/plugins/eap_radius/radius_client.c +++ b/src/libcharon/plugins/eap_radius/radius_client.c @@ -98,13 +98,14 @@ METHOD(radius_client_t, request, radius_message_t*, req->add(req, RAT_STATE, this->state); } socket = this->server->get_socket(this->server); - DBG1(DBG_CFG, "sending RADIUS %N to %#H", radius_message_code_names, - req->get_code(req), this->server->get_address(this->server)); + DBG1(DBG_CFG, "sending RADIUS %N to server '%s'", radius_message_code_names, + req->get_code(req), this->server->get_name(this->server)); res = socket->request(socket, req); if (res) { - DBG1(DBG_CFG, "received RADIUS %N from %#H", radius_message_code_names, - res->get_code(res), this->server->get_address(this->server)); + DBG1(DBG_CFG, "received RADIUS %N from server '%s'", + radius_message_code_names, res->get_code(res), + this->server->get_name(this->server)); save_state(this, res); if (res->get_code(res) == RMC_ACCESS_ACCEPT) { @@ -128,6 +129,7 @@ METHOD(radius_client_t, get_msk, chunk_t, METHOD(radius_client_t, destroy, void, private_radius_client_t *this) { + this->server->destroy(this->server); chunk_clear(&this->msk); free(this->state.ptr); free(this); @@ -159,15 +161,16 @@ radius_client_t *radius_client_create() /* for two with equal preference, 50-50 chance */ (current == best && random() % 2 == 0)) { - DBG2(DBG_CFG, "RADIUS server %H is candidate: %d", - server->get_address(server), current); + DBG2(DBG_CFG, "RADIUS server '%s' is candidate: %d", + server->get_name(server), current); best = current; - this->server = server; + DESTROY_IF(this->server); + this->server = server->get_ref(server); } else { - DBG2(DBG_CFG, "RADIUS server %H skipped: %d", - server->get_address(server), current); + DBG2(DBG_CFG, "RADIUS server '%s' skipped: %d", + server->get_name(server), current); } } enumerator->destroy(enumerator); diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c index f54b8b2cd..3baf39807 100644 --- a/src/libcharon/plugins/eap_radius/radius_server.c +++ b/src/libcharon/plugins/eap_radius/radius_server.c @@ -32,11 +32,6 @@ struct private_radius_server_t { radius_server_t public; /** - * RADIUS server address - */ - host_t *host; - - /** * list of radius sockets, as radius_socket_t */ linked_list_t *sockets; @@ -57,9 +52,9 @@ struct private_radius_server_t { condvar_t *condvar; /** - * RADIUS secret + * Server name */ - chunk_t secret; + char *name; /** * NAS-Identifier @@ -80,6 +75,11 @@ struct private_radius_server_t { * Retry counter for unreachable servers */ int retry; + + /** + * reference count + */ + refcount_t ref; }; METHOD(radius_server_t, get_socket, radius_socket_t*, @@ -147,27 +147,37 @@ METHOD(radius_server_t, get_preference, int, return pref; } -METHOD(radius_server_t, get_address, host_t*, +METHOD(radius_server_t, get_name, char*, + private_radius_server_t *this) +{ + return this->name; +} + +METHOD(radius_server_t, get_ref, radius_server_t*, private_radius_server_t *this) { - return this->host; + ref_get(&this->ref); + return &this->public; } + METHOD(radius_server_t, destroy, void, private_radius_server_t *this) { - DESTROY_IF(this->host); - this->mutex->destroy(this->mutex); - this->condvar->destroy(this->condvar); - this->sockets->destroy_offset(this->sockets, - offsetof(radius_socket_t, destroy)); - free(this); + if (ref_put(&this->ref)) + { + this->mutex->destroy(this->mutex); + this->condvar->destroy(this->condvar); + this->sockets->destroy_offset(this->sockets, + offsetof(radius_socket_t, destroy)); + free(this); + } } /** * See header */ -radius_server_t *radius_server_create(char *server, u_int16_t port, +radius_server_t *radius_server_create(char *name, char *address, u_int16_t port, char *nas_identifier, char *secret, int sockets, int preference) { private_radius_server_t *this; @@ -179,7 +189,8 @@ radius_server_t *radius_server_create(char *server, u_int16_t port, .put_socket = _put_socket, .get_nas_identifier = _get_nas_identifier, .get_preference = _get_preference, - .get_address = _get_address, + .get_name = _get_name, + .get_ref = _get_ref, .destroy = _destroy, }, .reachable = TRUE, @@ -188,18 +199,14 @@ radius_server_t *radius_server_create(char *server, u_int16_t port, .sockets = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), - .host = host_create_from_dns(server, 0, port), + .name = name, .preference = preference, + .ref = 1, ); - if (!this->host) - { - destroy(this); - return NULL; - } while (sockets--) { - socket = radius_socket_create(this->host, + socket = radius_socket_create(address, port, chunk_create(secret, strlen(secret))); if (!socket) { diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h index ba4c94619..c59361c49 100644 --- a/src/libcharon/plugins/eap_radius/radius_server.h +++ b/src/libcharon/plugins/eap_radius/radius_server.h @@ -61,11 +61,18 @@ struct radius_server_t { int (*get_preference)(radius_server_t *this); /** - * Get the address of the RADIUS server. + * Get the name of the RADIUS server. * - * @return address, internal data + * @return server name */ - host_t* (*get_address)(radius_server_t *this); + char* (*get_name)(radius_server_t *this); + + /** + * Increase reference count of this server. + * + * @return this + */ + radius_server_t* (*get_ref)(radius_server_t *this); /** * Destroy a radius_server_t. @@ -76,14 +83,15 @@ struct radius_server_t { /** * Create a radius_server instance. * - * @param server server address + * @param name server name + * @param address server address * @param port server port * @param nas_identifier NAS-Identifier to use with this server * @param secret secret to use with this server * @param sockets number of sockets to create in pool * @param preference preference boost for this server */ -radius_server_t *radius_server_create(char *server, u_int16_t port, +radius_server_t *radius_server_create(char *name, char *address, u_int16_t port, char *nas_identifier, char *secret, int sockets, int preference); #endif /** RADIUS_SERVER_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_socket.c b/src/libcharon/plugins/eap_radius/radius_socket.c index f46c27ede..b3229c288 100644 --- a/src/libcharon/plugins/eap_radius/radius_socket.c +++ b/src/libcharon/plugins/eap_radius/radius_socket.c @@ -49,6 +49,16 @@ struct private_radius_socket_t { int fd; /** + * Server address + */ + char *address; + + /** + * Server port + */ + u_int16_t port; + + /** * current RADIUS identifier */ u_int8_t identifier; @@ -74,6 +84,45 @@ struct private_radius_socket_t { chunk_t secret; }; +/** + * Check or establish RADIUS connection + */ +static bool check_connection(private_radius_socket_t *this) +{ + if (this->fd == -1) + { + host_t *server; + + server = host_create_from_dns(this->address, AF_UNSPEC, this->port); + if (!server) + { + DBG1(DBG_CFG, "resolving RADIUS server address '%s' failed", + this->address); + return FALSE; + } + this->fd = socket(server->get_family(server), SOCK_DGRAM, IPPROTO_UDP); + if (this->fd == -1) + { + DBG1(DBG_CFG, "opening RADIUS socket for %#H failed: %s", + server, strerror(errno)); + server->destroy(server); + return FALSE; + } + if (connect(this->fd, server->get_sockaddr(server), + *server->get_sockaddr_len(server)) < 0) + { + DBG1(DBG_CFG, "connecting RADIUS socket to %#H failed: %s", + server, strerror(errno)); + server->destroy(server); + close(this->fd); + this->fd = -1; + return FALSE; + } + server->destroy(server); + } + return TRUE; +} + METHOD(radius_socket_t, request, radius_message_t*, private_radius_socket_t *this, radius_message_t *request) { @@ -85,6 +134,11 @@ METHOD(radius_socket_t, request, radius_message_t*, /* sign the request */ request->sign(request, this->rng, this->signer); + if (!check_connection(this)) + { + return NULL; + } + data = request->get_encoding(request); /* timeout after 2, 3, 4, 5 seconds */ for (i = 2; i <= 5; i++) @@ -257,14 +311,18 @@ METHOD(radius_socket_t, destroy, void, DESTROY_IF(this->hasher); DESTROY_IF(this->signer); DESTROY_IF(this->rng); - close(this->fd); + if (this->fd != -1) + { + close(this->fd); + } free(this); } /** * See header */ -radius_socket_t *radius_socket_create(host_t *host, chunk_t secret) +radius_socket_t *radius_socket_create(char *address, u_int16_t port, + chunk_t secret) { private_radius_socket_t *this; @@ -274,23 +332,11 @@ radius_socket_t *radius_socket_create(host_t *host, chunk_t secret) .decrypt_msk = _decrypt_msk, .destroy = _destroy, }, + .address = address, + .port = port, + .fd = -1, ); - this->fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP); - if (this->fd < 0) - { - DBG1(DBG_CFG, "opening RADIUS socket failed: %s", strerror(errno)); - free(this); - return NULL; - } - if (connect(this->fd, host->get_sockaddr(host), - *host->get_sockaddr_len(host)) < 0) - { - DBG1(DBG_CFG, "connecting RADIUS socket failed"); - close(this->fd); - free(this); - return NULL; - } this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128); this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h index fe8491a8f..2875008eb 100644 --- a/src/libcharon/plugins/eap_radius/radius_socket.h +++ b/src/libcharon/plugins/eap_radius/radius_socket.h @@ -34,7 +34,7 @@ struct radius_socket_t { /** * Send a RADIUS request, wait for response. - + * * The socket fills in RADIUS Message identifier, builds a * Request-Authenticator and calculates the Message-Authenticator * attribute. @@ -66,9 +66,11 @@ struct radius_socket_t { /** * Create a radius_socket instance. * - * @param host RADIUS server address to connect to + * @param address server name + * @param port server port * @param secret RADIUS secret */ -radius_socket_t *radius_socket_create(host_t *host, chunk_t secret); +radius_socket_t *radius_socket_create(char *address, u_int16_t port, + chunk_t secret); #endif /** RADIUS_SOCKET_H_ @}*/ diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in index 90f203f61..b9ab6656b 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c index a3506f4ba..083bf73a3 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c @@ -56,6 +56,11 @@ struct private_eap_sim_peer_t { identification_t *reauth; /** + * EAP message identifier + */ + u_int8_t identifier; + + /** * EAP-SIM crypto helper */ simaka_crypto_t *crypto; @@ -98,7 +103,7 @@ static chunk_t version = chunk_from_chars(0x00,0x01); * Create a SIM_CLIENT_ERROR */ static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, - u_int8_t identifier, simaka_client_error_t code) + simaka_client_error_t code) { simaka_message_t *message; eap_payload_t *out; @@ -106,7 +111,7 @@ static eap_payload_t* create_client_error(private_eap_sim_peer_t *this, DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code); - message = simaka_message_create(FALSE, identifier, EAP_SIM, + message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_CLIENT_ERROR, this->crypto); encoded = htons(code); message->add_attribute(message, AT_CLIENT_ERROR_CODE, @@ -164,8 +169,7 @@ static status_t process_start(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); return NEED_MORE; } @@ -177,8 +181,7 @@ static status_t process_start(private_eap_sim_peer_t *this, if (!supported) { DBG1(DBG_IKE, "server does not support EAP-SIM version number 1"); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNSUPPORTED_VERSION); + *out = create_client_error(this, SIM_UNSUPPORTED_VERSION); return NEED_MORE; } @@ -214,7 +217,7 @@ static status_t process_start(private_eap_sim_peer_t *this, free(this->nonce.ptr); rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_START, this->crypto); if (!this->reauth) { @@ -261,8 +264,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); return NEED_MORE; } @@ -277,8 +279,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN)) { DBG1(DBG_IKE, "no valid AT_RAND received"); - *out = create_client_error(this, in->get_identifier(in), - SIM_INSUFFICIENT_CHALLENGES); + *out = create_client_error(this, SIM_INSUFFICIENT_CHALLENGES); return NEED_MORE; } /* get two or three KCs/SRESes from SIM using RANDs */ @@ -290,8 +291,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, rands.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", @@ -316,8 +316,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, * parse() again after key derivation, reading encrypted attributes */ if (!in->verify(in, this->nonce) || !in->parse(in)) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } @@ -345,7 +344,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this, enumerator->destroy(enumerator); /* build response with AT_MAC, built over "EAP packet | n*SRES" */ - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_CHALLENGE, this->crypto); *out = message->generate(message, sreses); message->destroy(message); @@ -379,8 +378,7 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, { DBG1(DBG_IKE, "received %N, but not expected", simaka_subtype_names, SIM_REAUTHENTICATION); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } @@ -390,8 +388,7 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, /* verify MAC and parse again with decryption key */ if (!in->verify(in, chunk_empty) || !in->parse(in)) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } @@ -412,8 +409,7 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, default: if (!simaka_attribute_skippable(type)) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); enumerator->destroy(enumerator); return NEED_MORE; } @@ -425,12 +421,11 @@ static status_t process_reauthentication(private_eap_sim_peer_t *this, if (!nonce.len || !counter.len) { DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete"); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_REAUTHENTICATION, this->crypto); if (counter_too_small(this, counter)) { @@ -503,40 +498,37 @@ static status_t process_notification(private_eap_sim_peer_t *this, if (success) { /* empty notification reply */ - message = simaka_message_create(FALSE, in->get_identifier(in), EAP_SIM, + message = simaka_message_create(FALSE, this->identifier, EAP_SIM, SIM_NOTIFICATION, this->crypto); *out = message->generate(message, chunk_empty); message->destroy(message); } else { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); } return NEED_MORE; } -/** - * Implementation of eap_method_t.process - */ -static status_t process(private_eap_sim_peer_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process, status_t, + private_eap_sim_peer_t *this, eap_payload_t *in, eap_payload_t **out) { simaka_message_t *message; status_t status; + /* store received EAP message identifier */ + this->identifier = in->get_identifier(in); + message = simaka_message_create_from_payload(in, this->crypto); if (!message) { - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } if (!message->parse(message)) { message->destroy(message); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); return NEED_MORE; } switch (message->get_subtype(message)) @@ -556,8 +548,7 @@ static status_t process(private_eap_sim_peer_t *this, default: DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N", simaka_subtype_names, message->get_subtype(message)); - *out = create_client_error(this, in->get_identifier(in), - SIM_UNABLE_TO_PROCESS); + *out = create_client_error(this, SIM_UNABLE_TO_PROCESS); status = NEED_MORE; break; } @@ -565,28 +556,22 @@ static status_t process(private_eap_sim_peer_t *this, return status; } -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_sim_peer_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate, status_t, + private_eap_sim_peer_t *this, eap_payload_t **out) { /* peer never initiates */ return FAILED; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_sim_peer_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_sim_peer_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_SIM; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_sim_peer_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_sim_peer_t *this, chunk_t *msk) { if (this->msk.ptr) { @@ -596,18 +581,26 @@ static status_t get_msk(private_eap_sim_peer_t *this, chunk_t *msk) return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_sim_peer_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_sim_peer_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_sim_peer_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_sim_peer_t *this) { return TRUE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_sim_peer_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_sim_peer_t *this) { this->permanent->destroy(this->permanent); DESTROY_IF(this->pseudonym); @@ -625,28 +618,32 @@ static void destroy(private_eap_sim_peer_t *this) eap_sim_peer_t *eap_sim_peer_create(identification_t *server, identification_t *peer) { - private_eap_sim_peer_t *this = malloc_thing(private_eap_sim_peer_t); - - this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.interface.destroy = (void(*)(eap_method_t*))destroy; + private_eap_sim_peer_t *this; + + INIT(this, + .public = { + .interface = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .crypto = simaka_crypto_create(), + ); - this->crypto = simaka_crypto_create(); if (!this->crypto) { free(this); return NULL; } + this->permanent = peer->clone(peer); - this->pseudonym = NULL; - this->reauth = NULL; this->tries = MAX_TRIES; - this->version_list = chunk_empty; - this->nonce = chunk_empty; - this->msk = chunk_empty; return &this->public; } diff --git a/src/libcharon/plugins/eap_sim/eap_sim_plugin.c b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c index f0c972253..b15292544 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_plugin.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_plugin.c @@ -20,10 +20,14 @@ #include <daemon.h> -/** - * Implementation of plugin_t.destroy - */ -static void destroy(eap_sim_plugin_t *this) +METHOD(plugin_t, get_name, char*, + eap_sim_plugin_t *this) +{ + return "eap-sim"; +} + +METHOD(plugin_t, destroy, void, + eap_sim_plugin_t *this) { charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_sim_server_create); @@ -37,9 +41,15 @@ static void destroy(eap_sim_plugin_t *this) */ plugin_t *eap_sim_plugin_create() { - eap_sim_plugin_t *this = malloc_thing(eap_sim_plugin_t); - - this->plugin.destroy = (void(*)(plugin_t*))destroy; + eap_sim_plugin_t *this; + + INIT(this, + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + ); charon->eap->add_method(charon->eap, EAP_SIM, 0, EAP_SERVER, (eap_constructor_t)eap_sim_server_create); diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c index f6d5df09b..d1dfde5d6 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_server.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c @@ -107,10 +107,8 @@ struct private_eap_sim_server_t { /* version of SIM protocol we speak */ static chunk_t version = chunk_from_chars(0x00,0x01); -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate, status_t, + private_eap_sim_server_t *this, eap_payload_t **out) { simaka_message_t *message; @@ -479,11 +477,8 @@ static status_t process_client_error(private_eap_sim_server_t *this, return FAILED; } -/** - * Implementation of eap_method_t.process - */ -static status_t process(private_eap_sim_server_t *this, - eap_payload_t *in, eap_payload_t **out) +METHOD(eap_method_t, process, status_t, + private_eap_sim_server_t *this, eap_payload_t *in, eap_payload_t **out) { simaka_message_t *message; status_t status; @@ -522,19 +517,15 @@ static status_t process(private_eap_sim_server_t *this, return status; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_sim_server_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_sim_server_t *this, u_int32_t *vendor) { *vendor = 0; return EAP_SIM; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_sim_server_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_sim_server_t *this, chunk_t *msk) { if (this->msk.ptr) { @@ -544,18 +535,26 @@ static status_t get_msk(private_eap_sim_server_t *this, chunk_t *msk) return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_sim_server_t *this) +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_sim_server_t *this) +{ + return this->identifier; +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_sim_server_t *this, u_int8_t identifier) +{ + this->identifier = identifier; +} + +METHOD(eap_method_t, is_mutual, bool, + private_eap_sim_server_t *this) { return TRUE; } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_sim_server_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_sim_server_t *this) { this->crypto->destroy(this->crypto); this->permanent->destroy(this->permanent); @@ -574,29 +573,31 @@ static void destroy(private_eap_sim_server_t *this) eap_sim_server_t *eap_sim_server_create(identification_t *server, identification_t *peer) { - private_eap_sim_server_t *this = malloc_thing(private_eap_sim_server_t); + private_eap_sim_server_t *this; + + INIT(this, + .public = { + .interface = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + }, + .crypto = simaka_crypto_create(), + ); - this->public.interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.interface.destroy = (void(*)(eap_method_t*))destroy; - - this->crypto = simaka_crypto_create(); if (!this->crypto) { free(this); return NULL; } + this->permanent = peer->clone(peer); - this->pseudonym = NULL; - this->reauth = NULL; - this->sreses = chunk_empty; - this->nonce = chunk_empty; - this->msk = chunk_empty; - this->counter = chunk_empty; - this->pending = 0; this->use_reauth = this->use_pseudonym = this->use_permanent = lib->settings->get_bool(lib->settings, "charon.plugins.eap-sim.request_identity", TRUE); diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index 3cd766a75..5662a1c53 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c index d132a38f6..5397c418e 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c @@ -35,11 +35,9 @@ struct private_eap_sim_file_card_t { eap_sim_file_triplets_t *triplets; }; -/** - * Implementation of sim_card_t.get_triplet - */ -static bool get_triplet(private_eap_sim_file_card_t *this, - identification_t *id, char *rand, char *sres, char *kc) +METHOD(sim_card_t, get_triplet, bool, + private_eap_sim_file_card_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { enumerator_t *enumerator; identification_t *cand; @@ -68,18 +66,16 @@ static bool get_triplet(private_eap_sim_file_card_t *this, return FALSE; } -/** - * Implementation of sim_card_t.get_quintuplet - */ -static status_t get_quintuplet() +METHOD(sim_card_t, get_quintuplet, status_t, + private_eap_sim_file_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) { return NOT_SUPPORTED; } -/** - * Implementation of eap_sim_file_card_t.destroy. - */ -static void destroy(private_eap_sim_file_card_t *this) +METHOD(eap_sim_file_card_t, destroy, void, + private_eap_sim_file_card_t *this) { free(this); } @@ -89,18 +85,23 @@ static void destroy(private_eap_sim_file_card_t *this) */ eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets) { - private_eap_sim_file_card_t *this = malloc_thing(private_eap_sim_file_card_t); - - this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet; - this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet; - this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))return_null; - this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop; - this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop; - this->public.destroy = (void(*)(eap_sim_file_card_t*))destroy; - - this->triplets = triplets; + private_eap_sim_file_card_t *this; + + INIT(this, + .public = { + .card = { + .get_triplet = _get_triplet, + .get_quintuplet = _get_quintuplet, + .resync = (void*)return_false, + .get_pseudonym = (void*)return_null, + .set_pseudonym = (void*)nop, + .get_reauth = (void*)return_null, + .set_reauth = (void*)nop, + }, + .destroy = _destroy, + }, + .triplets = triplets, + ); return &this->public; } diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c index 4f25c35ea..0ab5a1848 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_plugin.c @@ -50,10 +50,14 @@ struct private_eap_sim_file_t { eap_sim_file_triplets_t *triplets; }; -/** - * Implementation of eap_sim_file_t.destroy. - */ -static void destroy(private_eap_sim_file_t *this) +METHOD(plugin_t, get_name, char*, + private_eap_sim_file_t *this) +{ + return "eap-sim-file"; +} + +METHOD(plugin_t, destroy, void, + private_eap_sim_file_t *this) { charon->sim->remove_card(charon->sim, &this->card->card); charon->sim->remove_provider(charon->sim, &this->provider->provider); @@ -68,11 +72,19 @@ static void destroy(private_eap_sim_file_t *this) */ plugin_t *eap_sim_file_plugin_create() { - private_eap_sim_file_t *this = malloc_thing(private_eap_sim_file_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_eap_sim_file_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .triplets = eap_sim_file_triplets_create(TRIPLET_FILE), + ); - this->triplets = eap_sim_file_triplets_create(TRIPLET_FILE); this->provider = eap_sim_file_provider_create(this->triplets); if (!this->provider) { diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c index 9bee31fc3..38b651404 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_provider.c @@ -35,11 +35,9 @@ struct private_eap_sim_file_provider_t { eap_sim_file_triplets_t *triplets; }; -/** - * Implementation of sim_provider_t.get_triplet - */ -static bool get_triplet(private_eap_sim_file_provider_t *this, - identification_t *id, char *rand, char *sres, char *kc) +METHOD(sim_provider_t, get_triplet, bool, + private_eap_sim_file_provider_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { enumerator_t *enumerator; identification_t *cand; @@ -61,10 +59,8 @@ static bool get_triplet(private_eap_sim_file_provider_t *this, return FALSE; } -/** - * Implementation of eap_sim_file_provider_t.destroy. - */ -static void destroy(private_eap_sim_file_provider_t *this) +METHOD(eap_sim_file_provider_t, destroy, void, + private_eap_sim_file_provider_t *this) { free(this); } @@ -75,18 +71,23 @@ static void destroy(private_eap_sim_file_provider_t *this) eap_sim_file_provider_t *eap_sim_file_provider_create( eap_sim_file_triplets_t *triplets) { - private_eap_sim_file_provider_t *this = malloc_thing(private_eap_sim_file_provider_t); - - this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet; - this->public.provider.get_quintuplet = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))return_false; - this->public.provider.resync = (bool(*)(sim_provider_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false; - this->public.provider.is_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.gen_pseudonym = (identification_t*(*)(sim_provider_t*, identification_t *id))return_null; - this->public.provider.is_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char [HASH_SIZE_SHA1], u_int16_t *counter))return_null; - this->public.provider.gen_reauth = (identification_t*(*)(sim_provider_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))return_null; - this->public.destroy = (void(*)(eap_sim_file_provider_t*))destroy; + private_eap_sim_file_provider_t *this; - this->triplets = triplets; + INIT(this, + .public = { + .provider = { + .get_triplet = _get_triplet, + .get_quintuplet = (void*)return_false, + .resync = (void*)return_false, + .is_pseudonym = (void*)return_null, + .gen_pseudonym = (void*)return_null, + .is_reauth = (void*)return_null, + .gen_reauth = (void*)return_null, + }, + .destroy = _destroy, + }, + .triplets = triplets, + ); return &this->public; } diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c index 6b7d99fb7..c693923fe 100644 --- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c +++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_triplets.c @@ -117,10 +117,8 @@ static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **ims return FALSE; } -/** - * Implementation of eap_sim_file_triplets_t.create_enumerator - */ -static enumerator_t* create_enumerator(private_eap_sim_file_triplets_t *this) +METHOD(eap_sim_file_triplets_t, create_enumerator, enumerator_t*, + private_eap_sim_file_triplets_t *this) { triplet_enumerator_t *enumerator = malloc_thing(triplet_enumerator_t); @@ -230,10 +228,8 @@ static void read_triplets(private_eap_sim_file_triplets_t *this, char *path) this->triplets->get_count(this->triplets), path); } -/** - * Implementation of eap_sim_file_triplets_t.destroy. - */ -static void destroy(private_eap_sim_file_triplets_t *this) +METHOD(eap_sim_file_triplets_t, destroy, void, + private_eap_sim_file_triplets_t *this) { this->triplets->destroy_function(this->triplets, (void*)triplet_destroy); this->mutex->destroy(this->mutex); @@ -245,14 +241,16 @@ static void destroy(private_eap_sim_file_triplets_t *this) */ eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file) { - private_eap_sim_file_triplets_t *this = malloc_thing(private_eap_sim_file_triplets_t); - - this->public.create_enumerator = (enumerator_t*(*)(eap_sim_file_triplets_t*))create_enumerator; - this->public.destroy = (void(*)(eap_sim_file_triplets_t*))destroy; - - this->triplets = linked_list_create(); - this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); + private_eap_sim_file_triplets_t *this; + INIT(this, + .public = { + .create_enumerator = _create_enumerator, + .destroy = _destroy, + }, + .triplets = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); read_triplets(this, file); return &this->public; diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am new file mode 100644 index 000000000..2d75fe3ad --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am @@ -0,0 +1,18 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic ${pcsclite_CFLAGS} + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la +else +plugin_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la +endif + +libstrongswan_eap_sim_pcsc_la_SOURCES = \ + eap_sim_pcsc_plugin.h eap_sim_pcsc_plugin.c \ + eap_sim_pcsc_card.h eap_sim_pcsc_card.c + +libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in new file mode 100644 index 000000000..a8249a7ac --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in @@ -0,0 +1,611 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/libcharon/plugins/eap_sim_pcsc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_eap_sim_pcsc_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_eap_sim_pcsc_la_OBJECTS = eap_sim_pcsc_plugin.lo \ + eap_sim_pcsc_card.lo +libstrongswan_eap_sim_pcsc_la_OBJECTS = \ + $(am_libstrongswan_eap_sim_pcsc_la_OBJECTS) +libstrongswan_eap_sim_pcsc_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_eap_sim_pcsc_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_eap_sim_pcsc_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_eap_sim_pcsc_la_rpath = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_eap_sim_pcsc_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eap_sim_pcsc_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic ${pcsclite_CFLAGS} +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la +libstrongswan_eap_sim_pcsc_la_SOURCES = \ + eap_sim_pcsc_plugin.h eap_sim_pcsc_plugin.c \ + eap_sim_pcsc_card.h eap_sim_pcsc_card.c + +libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version +libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim_pcsc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/eap_sim_pcsc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-eap-sim-pcsc.la: $(libstrongswan_eap_sim_pcsc_la_OBJECTS) $(libstrongswan_eap_sim_pcsc_la_DEPENDENCIES) + $(libstrongswan_eap_sim_pcsc_la_LINK) $(am_libstrongswan_eap_sim_pcsc_la_rpath) $(libstrongswan_eap_sim_pcsc_la_OBJECTS) $(libstrongswan_eap_sim_pcsc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_pcsc_card.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_sim_pcsc_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(plugindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + ctags distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pluginLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-pluginLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c new file mode 100644 index 000000000..d0a2718f3 --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2011 Duncan Salerno + * + * 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_sim_pcsc_card.h" + +#include <PCSC/wintypes.h> +#include <PCSC/winscard.h> +#include <daemon.h> + +typedef struct private_eap_sim_pcsc_card_t private_eap_sim_pcsc_card_t; + +/** + * Private data of an eap_sim_pcsc_card_t object. + */ +struct private_eap_sim_pcsc_card_t { + + /** + * Public eap_sim_pcsc_card_t interface. + */ + eap_sim_pcsc_card_t public; +}; + +/** + * Maximum length for an IMSI. + */ +#define SIM_IMSI_MAX_LEN 15 + +/** + * Length of the status at the end of response APDUs. + */ +#define APDU_STATUS_LEN 2 + +/** + * First byte of status word indicating success. + */ +#define APDU_SW1_SUCCESS 0x90 + +/** + * First byte of status word indicating there is response data to be read. + */ +#define APDU_SW1_RESPONSE_DATA 0x9f + +/** + * Decode IMSI EF (Elementary File) into an ASCII string + */ +static bool decode_imsi_ef(unsigned char *input, int input_len, char *output) +{ + /* Only digits 0-9 valid in IMSIs */ + static const char bcd_num_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '\0', '\0', '\0', '\0', '\0', '\0' + }; + int i; + + /* Check length byte matches how many bytes we have, and that input + * is correct length for an IMSI */ + if (input[0] != input_len-1 || input_len < 2 || input_len > 9) + { + return FALSE; + } + + /* Check type byte is IMSI (bottom 3 bits == 001) */ + if ((input[1] & 0x07) != 0x01) + { + return FALSE; + } + *output++ = bcd_num_digits[input[1] >> 4]; + + for (i = 2; i < input_len; i++) + { + *output++ = bcd_num_digits[input[i] & 0xf]; + *output++ = bcd_num_digits[input[i] >> 4]; + } + + *output++ = '\0'; + return TRUE; +} + +METHOD(sim_card_t, get_triplet, bool, + private_eap_sim_pcsc_card_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) +{ + status_t found = FALSE; + LONG rv; + SCARDCONTEXT hContext; + DWORD dwReaders; + LPSTR mszReaders; + char *cur_reader; + char full_nai[128]; + SCARDHANDLE hCard; + enum { DISCONNECTED, CONNECTED, TRANSACTION } hCard_status = DISCONNECTED; + + snprintf(full_nai, sizeof(full_nai), "%Y", id); + + DBG2(DBG_IKE, "looking for triplet: %Y rand %b", id, rand, SIM_RAND_LEN); + + rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardEstablishContext: %s", pcsc_stringify_error(rv)); + return FALSE; + } + + rv = SCardListReaders(hContext, NULL, NULL, &dwReaders); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardListReaders: %s", pcsc_stringify_error(rv)); + return FALSE; + } + mszReaders = malloc(sizeof(char)*dwReaders); + + rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardListReaders: %s", pcsc_stringify_error(rv)); + return FALSE; + } + + /* mszReaders is a multi-string of readers, separated by '\0' and + * terminated by an additional '\0' */ + for (cur_reader = mszReaders; *cur_reader != '\0' && found == FALSE; + cur_reader += strlen(cur_reader) + 1) + { + DWORD dwActiveProtocol = -1; + SCARD_IO_REQUEST *pioSendPci; + SCARD_IO_REQUEST pioRecvPci; + BYTE pbRecvBuffer[64]; + DWORD dwRecvLength; + char imsi[SIM_IMSI_MAX_LEN + 1]; + + /* See GSM 11.11 for SIM APDUs */ + static const BYTE pbSelectMF[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00 }; + static const BYTE pbSelectDFGSM[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x7f, 0x20 }; + static const BYTE pbSelectIMSI[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x6f, 0x07 }; + static const BYTE pbReadBinary[] = { 0xa0, 0xb0, 0x00, 0x00, 0x09 }; + BYTE pbRunGSMAlgorithm[5 + SIM_RAND_LEN] = { 0xa0, 0x88, 0x00, 0x00, 0x10 }; + static const BYTE pbGetResponse[] = { 0xa0, 0xc0, 0x00, 0x00, 0x0c }; + + /* If on 2nd or later reader, make sure we end the transaction + * and disconnect card in the previous reader */ + switch (hCard_status) + { + case TRANSACTION: + SCardEndTransaction(hCard, SCARD_LEAVE_CARD); + /* FALLTHRU */ + case CONNECTED: + SCardDisconnect(hCard, SCARD_LEAVE_CARD); + /* FALLTHRU */ + case DISCONNECTED: + hCard_status = DISCONNECTED; + } + + /* Copy RAND into APDU */ + memcpy(pbRunGSMAlgorithm + 5, rand, SIM_RAND_LEN); + + rv = SCardConnect(hContext, cur_reader, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardConnect: %s", pcsc_stringify_error(rv)); + continue; + } + hCard_status = CONNECTED; + + switch(dwActiveProtocol) + { + case SCARD_PROTOCOL_T0: + pioSendPci = SCARD_PCI_T0; + break; + case SCARD_PROTOCOL_T1: + pioSendPci = SCARD_PCI_T1; + break; + default: + DBG1(DBG_IKE, "Unknown SCARD_PROTOCOL"); + continue; + } + + /* Start transaction */ + rv = SCardBeginTransaction(hCard); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardBeginTransaction: %s", pcsc_stringify_error(rv)); + continue; + } + hCard_status = TRANSACTION; + + /* APDU: Select MF */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, pbSelectMF, sizeof(pbSelectMF), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) + { + DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, dwRecvLength); + continue; + } + + /* APDU: Select DF GSM */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, pbSelectDFGSM, sizeof(pbSelectDFGSM), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) + { + DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, dwRecvLength); + continue; + } + + /* APDU: Select IMSI */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, pbSelectIMSI, sizeof(pbSelectIMSI), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) + { + DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength); + continue; + } + + /* APDU: Read Binary (of IMSI) */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, pbReadBinary, sizeof(pbReadBinary), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS) + { + DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength); + continue; + } + + if (!decode_imsi_ef(pbRecvBuffer, dwRecvLength-APDU_STATUS_LEN, imsi)) + { + DBG1(DBG_IKE, "Couldn't decode IMSI EF: %b", + pbRecvBuffer, dwRecvLength); + continue; + } + + /* The IMSI could be post/prefixed in the full NAI, so just make sure + * it's in there */ + if (!(strlen(full_nai) && strstr(full_nai, imsi))) + { + DBG1(DBG_IKE, "Not the SIM we're looking for, IMSI: %s", imsi); + continue; + } + + /* APDU: Run GSM Algorithm */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, + pbRunGSMAlgorithm, sizeof(pbRunGSMAlgorithm), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA) + { + DBG1(DBG_IKE, "Run GSM Algorithm failed: %b", + pbRecvBuffer, dwRecvLength); + continue; + } + + /* APDU: Get Response (of Run GSM Algorithm) */ + dwRecvLength = sizeof(pbRecvBuffer); + rv = SCardTransmit(hCard, pioSendPci, pbGetResponse, sizeof(pbGetResponse), + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv)); + continue; + } + + if (dwRecvLength < APDU_STATUS_LEN || + pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS) + { + DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, dwRecvLength); + continue; + } + + /* Extract out Kc and SRES from response */ + if (dwRecvLength == SIM_SRES_LEN + SIM_KC_LEN + APDU_STATUS_LEN) + { + memcpy(sres, pbRecvBuffer, SIM_SRES_LEN); + memcpy(kc, pbRecvBuffer+4, SIM_KC_LEN); + /* This will also cause the loop to exit */ + found = TRUE; + } + else + { + DBG1(DBG_IKE, "Get Response incorrect length: %b", + pbRecvBuffer, dwRecvLength); + continue; + } + + /* Transaction will be ended and card disconnected at the + * beginning of this loop or after this loop */ + } + + /* Make sure we end any previous transaction and disconnect card */ + switch (hCard_status) + { + case TRANSACTION: + SCardEndTransaction(hCard, SCARD_LEAVE_CARD); + /* FALLTHRU */ + case CONNECTED: + SCardDisconnect(hCard, SCARD_LEAVE_CARD); + /* FALLTHRU */ + case DISCONNECTED: + hCard_status = DISCONNECTED; + } + + rv = SCardReleaseContext(hContext); + if (rv != SCARD_S_SUCCESS) + { + DBG1(DBG_IKE, "SCardReleaseContext: %s", pcsc_stringify_error(rv)); + } + + free(mszReaders); + return found; +} + +METHOD(sim_card_t, get_quintuplet, status_t, + private_eap_sim_pcsc_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) +{ + return NOT_SUPPORTED; +} + +METHOD(eap_sim_pcsc_card_t, destroy, void, + private_eap_sim_pcsc_card_t *this) +{ + free(this); +} + +/** + * See header + */ +eap_sim_pcsc_card_t *eap_sim_pcsc_card_create() +{ + private_eap_sim_pcsc_card_t *this; + + INIT(this, + .public = { + .card = { + .get_triplet = _get_triplet, + .get_quintuplet = _get_quintuplet, + .resync = (void*)return_false, + .get_pseudonym = (void*)return_null, + .set_pseudonym = (void*)nop, + .get_reauth = (void*)return_null, + .set_reauth = (void*)nop, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h new file mode 100644 index 000000000..e7659656b --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_card.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Duncan Salerno + * + * 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_sim_pcsc_card eap_sim_pcsc_card + * @{ @ingroup eap_sim_pcsc + */ + +#ifndef EAP_SIM_PCSC_CARD_H_ +#define EAP_SIM_PCSC_CARD_H_ + +#include <sa/authenticators/eap/sim_manager.h> + +typedef struct eap_sim_pcsc_card_t eap_sim_pcsc_card_t; + +/** + * SIM card implementation using a PCSC reader. + */ +struct eap_sim_pcsc_card_t { + + /** + * Implements sim_card_t interface + */ + sim_card_t card; + + /** + * Destroy a eap_sim_pcsc_card_t. + */ + void (*destroy)(eap_sim_pcsc_card_t *this); +}; + +/** + * Create a eap_sim_pcsc_card instance. + */ +eap_sim_pcsc_card_t *eap_sim_pcsc_card_create(); + +#endif /** EAP_SIM_PCSC_CARD_H_ @}*/ diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c new file mode 100644 index 000000000..44096455e --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 Duncan Salerno + * + * 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_sim_pcsc_plugin.h" +#include "eap_sim_pcsc_card.h" + +#include <daemon.h> + +typedef struct private_eap_sim_pcsc_plugin_t private_eap_sim_pcsc_plugin_t; + +/** + * Private data of an eap_sim_pcsc_t object. + */ +struct private_eap_sim_pcsc_plugin_t { + + /** + * Public eap_sim_pcsc_plugin_t interface. + */ + eap_sim_pcsc_plugin_t public; + + /** + * SIM card + */ + eap_sim_pcsc_card_t *card; +}; + +METHOD(plugin_t, get_name, char*, + private_eap_sim_pcsc_plugin_t *this) +{ + return "eap-sim-pcsc"; +} + +METHOD(plugin_t, destroy, void, + private_eap_sim_pcsc_plugin_t *this) +{ + charon->sim->remove_card(charon->sim, &this->card->card); + this->card->destroy(this->card); + free(this); +} + +/** + * See header + */ +plugin_t *eap_sim_pcsc_plugin_create() +{ + private_eap_sim_pcsc_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .card = eap_sim_pcsc_card_create(), + ); + charon->sim->add_card(charon->sim, &this->card->card); + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.h b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.h new file mode 100644 index 000000000..a03ca1f9c --- /dev/null +++ b/src/libcharon/plugins/eap_sim_pcsc/eap_sim_pcsc_plugin.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 Duncan Salerno + * + * 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_sim_pcsc eap_sim_pcsc + * @ingroup cplugins + * + * @defgroup eap_sim_pcsc_plugin eap_sim_pcsc_plugin + * @{ @ingroup eap_sim_pcsc + */ + +#ifndef EAP_SIM_PCSC_PLUGIN_H_ +#define EAP_SIM_PCSC_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_sim_pcsc_plugin_t eap_sim_pcsc_plugin_t; + +/** + * Plugin to provide a SIM card from a PCSC reader. + */ +struct eap_sim_pcsc_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** EAP_SIM_PCSC_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index a48fb652a..98e80bc71 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -246,6 +246,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -269,6 +271,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c index 81b9d7b00..06631b1c5 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c +++ b/src/libcharon/plugins/eap_simaka_pseudonym/eap_simaka_pseudonym_plugin.c @@ -42,10 +42,14 @@ struct private_eap_simaka_pseudonym_t { eap_simaka_pseudonym_provider_t *provider; }; -/** - * Implementation of eap_simaka_pseudonym_t.destroy. - */ -static void destroy(private_eap_simaka_pseudonym_t *this) +METHOD(plugin_t, get_name, char*, + private_eap_simaka_pseudonym_t *this) +{ + return "eap-simaka-pseudonym"; +} + +METHOD(plugin_t, destroy, void, + private_eap_simaka_pseudonym_t *this) { charon->sim->remove_card(charon->sim, &this->card->card); charon->sim->remove_provider(charon->sim, &this->provider->provider); @@ -61,11 +65,17 @@ plugin_t *eap_simaka_pseudonym_plugin_create() { private_eap_simaka_pseudonym_t *this; - this = malloc_thing(private_eap_simaka_pseudonym_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .provider = eap_simaka_pseudonym_provider_create(), + ); - this->provider = eap_simaka_pseudonym_provider_create(); if (!this->provider) { free(this); diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index f2af3ae0d..56bc188b0 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c index 987a0e109..343e4eefb 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c +++ b/src/libcharon/plugins/eap_simaka_reauth/eap_simaka_reauth_plugin.c @@ -42,10 +42,14 @@ struct private_eap_simaka_reauth_t { eap_simaka_reauth_provider_t *provider; }; -/** - * Implementation of eap_simaka_reauth_t.destroy. - */ -static void destroy(private_eap_simaka_reauth_t *this) +METHOD(plugin_t, get_name, char*, + private_eap_simaka_reauth_t *this) +{ + return "eap-simaka-reauth"; +} + +METHOD(plugin_t, destroy, void, + private_eap_simaka_reauth_t *this) { charon->sim->remove_card(charon->sim, &this->card->card); charon->sim->remove_provider(charon->sim, &this->provider->provider); @@ -59,11 +63,19 @@ static void destroy(private_eap_simaka_reauth_t *this) */ plugin_t *eap_simaka_reauth_plugin_create() { - private_eap_simaka_reauth_t *this = malloc_thing(private_eap_simaka_reauth_t); + private_eap_simaka_reauth_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .provider = eap_simaka_reauth_provider_create(), + ); - this->provider = eap_simaka_reauth_provider_create(); if (!this->provider) { free(this); diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in index 9a58a6055..93c7aed03 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c index 1cc5352d8..5a528153d 100644 --- a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c @@ -47,6 +47,12 @@ struct private_eap_simaka_sql_t { database_t *db; }; +METHOD(plugin_t, get_name, char*, + private_eap_simaka_sql_t *this) +{ + return "eap-simaka-sql"; +} + METHOD(plugin_t, destroy, void, private_eap_simaka_sql_t *this) { @@ -87,6 +93,8 @@ plugin_t *eap_simaka_sql_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in index 9ebb85be9..c58bced06 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.in +++ b/src/libcharon/plugins/eap_tls/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c index efe72c437..39e1a60d9 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls.c +++ b/src/libcharon/plugins/eap_tls/eap_tls.c @@ -91,6 +91,18 @@ METHOD(eap_method_t, get_msk, status_t, return FAILED; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_tls_t *this) +{ + return this->tls_eap->get_identifier(this->tls_eap); +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_tls_t *this, u_int8_t identifier) +{ + this->tls_eap->set_identifier(this->tls_eap, identifier); +} + METHOD(eap_method_t, is_mutual, bool, private_eap_tls_t *this) { @@ -113,6 +125,7 @@ static eap_tls_t *eap_tls_create(identification_t *server, private_eap_tls_t *this; size_t frag_size; int max_msg_count; + bool include_length; tls_t *tls; INIT(this, @@ -123,6 +136,8 @@ static eap_tls_t *eap_tls_create(identification_t *server, .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, @@ -132,8 +147,11 @@ static eap_tls_t *eap_tls_create(identification_t *server, "charon.plugins.eap-tls.fragment_size", MAX_FRAGMENT_LEN); max_msg_count = lib->settings->get_int(lib->settings, "charon.plugins.eap-tls.max_message_count", MAX_MESSAGE_COUNT); + include_length = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-tls.include_length", TRUE); tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TLS, NULL); - this->tls_eap = tls_eap_create(EAP_TLS, tls, frag_size, max_msg_count); + this->tls_eap = tls_eap_create(EAP_TLS, tls, frag_size, max_msg_count, + include_length); if (!this->tls_eap) { free(this); diff --git a/src/libcharon/plugins/eap_tls/eap_tls_plugin.c b/src/libcharon/plugins/eap_tls/eap_tls_plugin.c index a7c040bf4..7afb79819 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls_plugin.c +++ b/src/libcharon/plugins/eap_tls/eap_tls_plugin.c @@ -19,6 +19,11 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + eap_tls_plugin_t *this) +{ + return "eap-tls"; +} METHOD(plugin_t, destroy, void, eap_tls_plugin_t *this) @@ -39,6 +44,8 @@ plugin_t *eap_tls_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in index cf75585ef..dfc052bf8 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.in +++ b/src/libcharon/plugins/eap_tnc/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index dd4ed5322..ab3f87688 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -92,6 +92,18 @@ METHOD(eap_method_t, get_msk, status_t, return FAILED; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_tnc_t *this) +{ + return this->tls_eap->get_identifier(this->tls_eap); +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_tnc_t *this, u_int8_t identifier) +{ + this->tls_eap->set_identifier(this->tls_eap, identifier); +} + METHOD(eap_method_t, is_mutual, bool, private_eap_tnc_t *this) { @@ -114,6 +126,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, private_eap_tnc_t *this; size_t frag_size; int max_msg_count; + bool include_length; char* protocol; tnccs_type_t type; tnccs_t *tnccs; @@ -126,6 +139,8 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, .get_type = _get_type, .is_mutual = _is_mutual, .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .destroy = _destroy, }, }, @@ -135,7 +150,9 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, "charon.plugins.eap-tnc.fragment_size", MAX_FRAGMENT_LEN); max_msg_count = lib->settings->get_int(lib->settings, "charon.plugins.eap-tnc.max_message_count", MAX_MESSAGE_COUNT); - protocol = lib->settings->get_str(lib->settings, + include_length = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-tnc.include_length", TRUE); + protocol = lib->settings->get_str(lib->settings, "charon.plugins.eap-tnc.protocol", "tnccs-1.1"); if (strcaseeq(protocol, "tnccs-2.0")) { @@ -156,7 +173,8 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, return NULL; } tnccs = charon->tnccs->create_instance(charon->tnccs, type, is_server); - this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size, max_msg_count); + this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, frag_size, + max_msg_count, include_length); if (!this->tls_eap) { free(this); diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c index 7430e4cac..93847e636 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + eap_tnc_plugin_t *this) +{ + return "eap-tnc"; +} + METHOD(plugin_t, destroy, void, eap_tnc_plugin_t *this) { @@ -37,6 +43,8 @@ plugin_t *eap_tnc_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in index ff67686b2..d0d5341e2 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.in +++ b/src/libcharon/plugins/eap_ttls/Makefile.in @@ -246,6 +246,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -269,6 +271,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c index a62af6ea4..7193bc9f0 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c @@ -93,6 +93,18 @@ METHOD(eap_method_t, get_msk, status_t, return FAILED; } +METHOD(eap_method_t, get_identifier, u_int8_t, + private_eap_ttls_t *this) +{ + return this->tls_eap->get_identifier(this->tls_eap); +} + +METHOD(eap_method_t, set_identifier, void, + private_eap_ttls_t *this, u_int8_t identifier) +{ + this->tls_eap->set_identifier(this->tls_eap, identifier); +} + METHOD(eap_method_t, is_mutual, bool, private_eap_ttls_t *this) { @@ -116,6 +128,7 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, private_eap_ttls_t *this; size_t frag_size; int max_msg_count; + bool include_length; tls_t *tls; INIT(this, @@ -125,6 +138,8 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, .process = _process, .get_type = _get_type, .is_mutual = _is_mutual, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, .get_msk = _get_msk, .destroy = _destroy, }, @@ -139,8 +154,11 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, "charon.plugins.eap-ttls.fragment_size", MAX_FRAGMENT_LEN); max_msg_count = lib->settings->get_int(lib->settings, "charon.plugins.eap-ttls.max_message_count", MAX_MESSAGE_COUNT); - tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TTLS, application); - this->tls_eap = tls_eap_create(EAP_TTLS, tls, frag_size, max_msg_count); + include_length = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-ttls.include_length", TRUE); + tls = tls_create(is_server, server, peer, TLS_PURPOSE_EAP_TTLS, application); + this->tls_eap = tls_eap_create(EAP_TTLS, tls, frag_size, max_msg_count, + include_length); if (!this->tls_eap) { application->destroy(application); diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c index 29b0a9303..931eb2e89 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c @@ -64,17 +64,6 @@ struct private_eap_ttls_peer_t { eap_ttls_avp_t *avp; }; -/** - * EAP packet format - */ -typedef struct __attribute__((packed)) { - u_int8_t code; - u_int8_t identifier; - u_int16_t length; - u_int8_t type; - u_int8_t data; -} eap_packet_t; - #define MAX_RADIUS_ATTRIBUTE_SIZE 253 METHOD(tls_application_t, process, status_t, @@ -174,17 +163,30 @@ METHOD(tls_application_t, process, status_t, return FAILED; } + /* yet another phase2 authentication? */ + if (this->method) + { + type = this->method->get_type(this->method, &vendor); + + if (type != received_type || vendor != received_vendor) + { + this->method->destroy(this->method); + this->method = NULL; + } + } + if (this->method == NULL) { if (received_vendor) { - DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d", - received_type, received_vendor); + DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d " + "(id 0x%02X)", received_type, received_vendor, + in->get_identifier(in)); } else { - DBG1(DBG_IKE, "server requested %N authentication", - eap_type_names, received_type); + DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", + eap_type_names, received_type, in->get_identifier(in)); } this->method = charon->eap->create_instance(charon->eap, received_type, received_vendor, @@ -196,18 +198,10 @@ METHOD(tls_application_t, process, status_t, in->destroy(in); return NEED_MORE; } + type = this->method->get_type(this->method, &vendor); this->start_phase2 = FALSE; } - type = this->method->get_type(this->method, &vendor); - - if (type != received_type || vendor != received_vendor) - { - DBG1(DBG_IKE, "received invalid EAP request"); - in->destroy(in); - return FAILED; - } - status = this->method->process(this->method, in, &this->out); in->destroy(in); @@ -216,13 +210,8 @@ METHOD(tls_application_t, process, status_t, case SUCCESS: this->method->destroy(this->method); this->method = NULL; - return NEED_MORE; + /* fall through to NEED_MORE */ case NEED_MORE: - if (type != EAP_TNC) - { - this->method->destroy(this->method); - this->method = NULL; - } return NEED_MORE; case FAILED: default: diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c index 48e759dcc..cbc3929bb 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_plugin.c @@ -19,6 +19,11 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + eap_ttls_plugin_t *this) +{ + return "eap-ttls"; +} METHOD(plugin_t, destroy, void, eap_ttls_plugin_t *this) @@ -39,6 +44,8 @@ plugin_t *eap_ttls_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index 21e8b78db..4ba29472d 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -241,6 +241,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -264,6 +266,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/farp/farp_plugin.c b/src/libcharon/plugins/farp/farp_plugin.c index d83bc1fd2..a30c11962 100644 --- a/src/libcharon/plugins/farp/farp_plugin.c +++ b/src/libcharon/plugins/farp/farp_plugin.c @@ -43,6 +43,12 @@ struct private_farp_plugin_t { farp_spoofer_t *spoofer; }; +METHOD(plugin_t, get_name, char*, + private_farp_plugin_t *this) +{ + return "farp"; +} + METHOD(plugin_t, destroy, void, private_farp_plugin_t *this) { @@ -62,6 +68,8 @@ plugin_t *farp_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index 2fcd7cc82..fe72c5c8e 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index 1a9425423..707add94d 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -91,6 +91,10 @@ METHOD(listener_t, child_keys, bool, { m->add_attribute(m, HA_ALG_INTEG, alg); } + if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, &alg, NULL)) + { + m->add_attribute(m, HA_ESN, alg); + } m->add_attribute(m, HA_NONCE_I, nonce_i); m->add_attribute(m, HA_NONCE_R, nonce_r); if (dh && dh->get_shared_secret(dh, &secret) == SUCCESS) diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 85dc0f4a4..0d0df8dd1 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -462,6 +462,7 @@ static void process_child_add(private_ha_dispatcher_t *this, u_int16_t inbound_cpi = 0, outbound_cpi = 0; u_int8_t mode = MODE_TUNNEL, ipcomp = 0; u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0; + u_int16_t esn = NO_EXT_SEQ_NUMBERS; u_int seg_i, seg_o; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; chunk_t encr_i, integ_i, encr_r, integ_r; @@ -512,6 +513,9 @@ static void process_child_add(private_ha_dispatcher_t *this, case HA_ALG_INTEG: integ = value.u16; break; + case HA_ESN: + esn = value.u16; + break; case HA_NONCE_I: nonce_i = value.chunk; break; @@ -558,6 +562,7 @@ static void process_child_add(private_ha_dispatcher_t *this, { proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); } + proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); keymat = ike_sa->get_keymat(ike_sa); if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL, diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index 7ce9cbe09..f98f78dd4 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -234,6 +234,7 @@ METHOD(ha_message_t, add_attribute, void, case HA_INBOUND_CPI: case HA_OUTBOUND_CPI: case HA_SEGMENT: + case HA_ESN: { u_int16_t val; @@ -447,6 +448,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, case HA_INBOUND_CPI: case HA_OUTBOUND_CPI: case HA_SEGMENT: + case HA_ESN: { if (this->buf.len < sizeof(u_int16_t)) { diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index 50e11830f..1f8eabd62 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -140,6 +140,8 @@ enum ha_message_attribute_t { HA_MID, /** u_int16_t, HA segment */ HA_SEGMENT, + /** u_int16_t, Extended Sequence numbers */ + HA_ESN, }; /** diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index 581294e60..b4bde5ea5 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -91,6 +91,12 @@ struct private_ha_plugin_t { ha_attribute_t *attr; }; +METHOD(plugin_t, get_name, char*, + private_ha_plugin_t *this) +{ + return "ha"; +} + METHOD(plugin_t, destroy, void, private_ha_plugin_t *this) { @@ -144,6 +150,8 @@ plugin_t *ha_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in index fa1194fd0..db3a7c702 100644 --- a/src/libcharon/plugins/led/Makefile.in +++ b/src/libcharon/plugins/led/Makefile.in @@ -240,6 +240,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -263,6 +265,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/led/led_plugin.c b/src/libcharon/plugins/led/led_plugin.c index 322d198ff..b6b69b466 100644 --- a/src/libcharon/plugins/led/led_plugin.c +++ b/src/libcharon/plugins/led/led_plugin.c @@ -37,6 +37,12 @@ struct private_led_plugin_t { led_listener_t *listener; }; +METHOD(plugin_t, get_name, char*, + private_led_plugin_t *this) +{ + return "led"; +} + METHOD(plugin_t, destroy, void, private_led_plugin_t *this) { @@ -55,6 +61,8 @@ plugin_t *led_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index c921ec3db..1e9a5fe82 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -246,6 +246,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -269,6 +271,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index ef9d7f9ef..fdec5300e 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -54,8 +54,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, - u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts) + u_int16_t cpi, bool encap, bool esn, bool inbound, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts) { return SUCCESS; } diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index 8fd65adfa..94115e307 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -146,10 +146,14 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) return JOB_REQUEUE_NONE; } -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_load_tester_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_load_tester_plugin_t *this) +{ + return "load-tester"; +} + +METHOD(plugin_t, destroy, void, + private_load_tester_plugin_t *this) { this->iterations = -1; this->mutex->lock(this->mutex); @@ -188,32 +192,39 @@ plugin_t *load_tester_plugin_create() return NULL; } - this = malloc_thing(private_load_tester_plugin_t); - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .delay = lib->settings->get_int(lib->settings, + "charon.plugins.load-tester.delay", 0), + .iterations = lib->settings->get_int(lib->settings, + "charon.plugins.load-tester.iterations", 1), + .initiators = lib->settings->get_int(lib->settings, + "charon.plugins.load-tester.initiators", 0), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .config = load_tester_config_create(), + .creds = load_tester_creds_create(), + .listener = load_tester_listener_create(shutdown_on), + ); lib->crypto->add_dh(lib->crypto, MODP_NULL, plugin_name, (dh_constructor_t)load_tester_diffie_hellman_create); + charon->backends->add_backend(charon->backends, &this->config->backend); + lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); + charon->bus->add_listener(charon->bus, &this->listener->listener); - this->delay = lib->settings->get_int(lib->settings, - "charon.plugins.load-tester.delay", 0); - this->iterations = lib->settings->get_int(lib->settings, - "charon.plugins.load-tester.iterations", 1); - this->initiators = lib->settings->get_int(lib->settings, - "charon.plugins.load-tester.initiators", 0); if (lib->settings->get_bool(lib->settings, "charon.plugins.load-tester.shutdown_when_complete", 0)) { shutdown_on = this->iterations * this->initiators; } - this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); - this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT); - this->config = load_tester_config_create(); - this->creds = load_tester_creds_create(); - this->listener = load_tester_listener_create(shutdown_on); - charon->backends->add_backend(charon->backends, &this->config->backend); - lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); - charon->bus->add_listener(charon->bus, &this->listener->listener); if (lib->settings->get_bool(lib->settings, "charon.plugins.load-tester.fake_kernel", FALSE)) diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in index 0ca1fa436..27e72295c 100644 --- a/src/libcharon/plugins/maemo/Makefile.in +++ b/src/libcharon/plugins/maemo/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/maemo/maemo_plugin.c b/src/libcharon/plugins/maemo/maemo_plugin.c index d4549f43a..38cb031b5 100644 --- a/src/libcharon/plugins/maemo/maemo_plugin.c +++ b/src/libcharon/plugins/maemo/maemo_plugin.c @@ -34,11 +34,16 @@ struct private_maemo_plugin_t { * service */ maemo_service_t *service; - }; +METHOD(plugin_t, get_name, char*, + private_maemo_plugin_t *this) +{ + return "maemo"; +} + METHOD(plugin_t, destroy, void, - private_maemo_plugin_t *this) + private_maemo_plugin_t *this) { this->service->destroy(this->service); free(this); @@ -54,6 +59,8 @@ plugin_t *maemo_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index 372a436a6..83b457b46 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/medcli/medcli_plugin.c b/src/libcharon/plugins/medcli/medcli_plugin.c index 6befbf440..469915476 100644 --- a/src/libcharon/plugins/medcli/medcli_plugin.c +++ b/src/libcharon/plugins/medcli/medcli_plugin.c @@ -54,10 +54,14 @@ struct private_medcli_plugin_t { medcli_listener_t *listener; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_medcli_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_medcli_plugin_t *this) +{ + return "medcli"; +} + +METHOD(plugin_t, destroy, void, + private_medcli_plugin_t *this) { charon->bus->remove_listener(charon->bus, &this->listener->listener); charon->backends->remove_backend(charon->backends, &this->config->backend); @@ -75,9 +79,17 @@ static void destroy(private_medcli_plugin_t *this) plugin_t *medcli_plugin_create() { char *uri; - private_medcli_plugin_t *this = malloc_thing(private_medcli_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_medcli_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + ); uri = lib->settings->get_str(lib->settings, "medcli.database", NULL); diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index 4bb65bd09..068f311a5 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.c b/src/libcharon/plugins/medsrv/medsrv_plugin.c index c150346cb..5df46d04f 100644 --- a/src/libcharon/plugins/medsrv/medsrv_plugin.c +++ b/src/libcharon/plugins/medsrv/medsrv_plugin.c @@ -48,10 +48,14 @@ struct private_medsrv_plugin_t { medsrv_config_t *config; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_medsrv_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_medsrv_plugin_t *this) +{ + return "medsrv"; +} + +METHOD(plugin_t, destroy, void, + private_medsrv_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); lib->credmgr->remove_set(lib->credmgr, &this->creds->set); @@ -67,9 +71,17 @@ static void destroy(private_medsrv_plugin_t *this) plugin_t *medsrv_plugin_create() { char *uri; - private_medsrv_plugin_t *this = malloc_thing(private_medsrv_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_medsrv_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + ); uri = lib->settings->get_str(lib->settings, "medsrv.database", NULL); diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in index 69af7bf83..308d27229 100644 --- a/src/libcharon/plugins/nm/Makefile.in +++ b/src/libcharon/plugins/nm/Makefile.in @@ -242,6 +242,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -265,6 +267,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c index fd0580bd6..f1d3be7a5 100644 --- a/src/libcharon/plugins/nm/nm_plugin.c +++ b/src/libcharon/plugins/nm/nm_plugin.c @@ -67,10 +67,14 @@ static job_requeue_t run(private_nm_plugin_t *this) return JOB_REQUEUE_NONE; } -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_nm_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_nm_plugin_t *this) +{ + return "nm"; +} + +METHOD(plugin_t, destroy, void, + private_nm_plugin_t *this) { if (this->loop) { @@ -96,22 +100,29 @@ static void destroy(private_nm_plugin_t *this) */ plugin_t *nm_plugin_create() { - private_nm_plugin_t *this = malloc_thing(private_nm_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_nm_plugin_t *this; - this->loop = NULL; g_type_init (); if (!g_thread_supported()) { g_thread_init(NULL); } - this->creds = nm_creds_create(); - this->handler = nm_handler_create(); + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .creds = nm_creds_create(), + .handler = nm_handler_create(), + .plugin = nm_strongswan_plugin_new(this->creds, this->handler), + ); + hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); lib->credmgr->add_set(lib->credmgr, &this->creds->set); - this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); if (!this->plugin) { DBG1(DBG_CFG, "DBUS binding failed"); diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index 3d2cef13c..e36fa6bb4 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -241,6 +241,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -264,6 +266,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index 60937f23d..d20f32248 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -707,10 +707,14 @@ static job_requeue_t dispatch(private_smp_t *this) return JOB_REQUEUE_DIRECT; } -/** - * Implementation of itnerface_t.destroy. - */ -static void destroy(private_smp_t *this) +METHOD(plugin_t, get_name, char*, + private_smp_t *this) +{ + return "smp"; +} + +METHOD(plugin_t, destroy, void, + private_smp_t *this) { this->job->cancel(this->job); close(this->socket); @@ -723,10 +727,18 @@ static void destroy(private_smp_t *this) plugin_t *smp_plugin_create() { struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"}; - private_smp_t *this = malloc_thing(private_smp_t); + private_smp_t *this; mode_t old; - this->public.plugin.destroy = (void (*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + ); /* set up unix socket */ this->socket = socket(AF_UNIX, SOCK_STREAM, 0); diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index b82372e30..95cb04d14 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.c b/src/libcharon/plugins/socket_default/socket_default_plugin.c index b5dea68b6..1bc8244d5 100644 --- a/src/libcharon/plugins/socket_default/socket_default_plugin.c +++ b/src/libcharon/plugins/socket_default/socket_default_plugin.c @@ -32,9 +32,14 @@ struct private_socket_default_plugin_t { * Implements plugin interface */ socket_default_plugin_t public; - }; +METHOD(plugin_t, get_name, char*, + private_socket_default_plugin_t *this) +{ + return "socket-default"; +} + METHOD(plugin_t, destroy, void, private_socket_default_plugin_t *this) { @@ -53,6 +58,8 @@ plugin_t *socket_default_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 7a49088b2..97e3a713d 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c index a6ff14efd..c5ea37a10 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c @@ -32,9 +32,14 @@ struct private_socket_dynamic_plugin_t { * Implements plugin interface */ socket_dynamic_plugin_t public; - }; +METHOD(plugin_t, get_name, char*, + private_socket_dynamic_plugin_t *this) +{ + return "socket-dynamic"; +} + METHOD(plugin_t, destroy, void, private_socket_dynamic_plugin_t *this) { @@ -53,6 +58,8 @@ plugin_t *socket_dynamic_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in index 744b12fcf..6f1a09c88 100644 --- a/src/libcharon/plugins/socket_raw/Makefile.in +++ b/src/libcharon/plugins/socket_raw/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c index 17a3a8db7..5bd28bd42 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c @@ -32,9 +32,14 @@ struct private_socket_raw_plugin_t { * Implements plugin interface */ socket_raw_plugin_t public; - }; +METHOD(plugin_t, get_name, char*, + private_socket_raw_plugin_t *this) +{ + return "socket-raw"; +} + METHOD(plugin_t, destroy, void, private_socket_raw_plugin_t *this) { @@ -53,6 +58,8 @@ plugin_t *socket_raw_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index 4244d3b5e..d7b43dcc9 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -241,6 +241,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -264,6 +266,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c index ad1eb91b1..d915d4696 100644 --- a/src/libcharon/plugins/sql/sql_plugin.c +++ b/src/libcharon/plugins/sql/sql_plugin.c @@ -53,6 +53,12 @@ struct private_sql_plugin_t { sql_logger_t *logger; }; +METHOD(plugin_t, get_name, char*, + private_sql_plugin_t *this) +{ + return "sql"; +} + METHOD(plugin_t, destroy, void, private_sql_plugin_t *this) { @@ -84,6 +90,8 @@ plugin_t *sql_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index ccf3eeede..fd859daeb 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index ea7d17592..2b3164384 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -409,7 +409,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } else { - DBG1(DBG_CFG, "CA certificate %s not found, discarding CA " + DBG1(DBG_CFG, "CA certificate \"%s\" not found, discarding CA " "constraint", ca); } } diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index 3541ab8f9..4943ee670 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -92,48 +92,94 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name) return found; } +/** + * call the charon controller to initiate the connection + */ +static void charon_initiate(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, + stroke_msg_t *msg, FILE *out) +{ + if (msg->output_verbosity < 0) + { + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + NULL, NULL); + } + else + { + stroke_log_info_t info = { msg->output_verbosity, out }; + + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + (controller_cb_t)stroke_log, &info); + } +} + METHOD(stroke_control_t, initiate, void, private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { + child_cfg_t *child_cfg = NULL; peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; - stroke_log_info_t info; + enumerator_t *enumerator; + bool empty = TRUE; peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, msg->initiate.name); - if (peer_cfg == NULL) - { - DBG1(DBG_CFG, "no config named '%s'\n", msg->initiate.name); - return; - } - if (peer_cfg->get_ike_version(peer_cfg) != 2) + if (peer_cfg) { - DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config", - peer_cfg->get_ike_version(peer_cfg)); - peer_cfg->destroy(peer_cfg); - return; - } + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config", + peer_cfg->get_ike_version(peer_cfg)); + peer_cfg->destroy(peer_cfg); + return; + } - child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name); - if (child_cfg == NULL) - { - DBG1(DBG_CFG, "no child config named '%s'\n", msg->initiate.name); - peer_cfg->destroy(peer_cfg); - return; - } + child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name); + if (child_cfg == NULL) + { + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, &child_cfg)) + { + empty = FALSE; + charon_initiate(peer_cfg->get_ref(peer_cfg), + child_cfg->get_ref(child_cfg), msg, out); + } + enumerator->destroy(enumerator); - if (msg->output_verbosity < 0) - { - charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - NULL, NULL); + if (empty) + { + DBG1(DBG_CFG, "no child config named '%s'", msg->initiate.name); + fprintf(out, "no child config named '%s'\n", msg->initiate.name); + } + peer_cfg->destroy(peer_cfg); + return; + } } else { - info.out = out; - info.level = msg->output_verbosity; - charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - (controller_cb_t)stroke_log, &info); + enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends, + NULL, NULL, NULL, NULL); + while (enumerator->enumerate(enumerator, &peer_cfg)) + { + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + continue; + } + child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name); + if (child_cfg) + { + peer_cfg->get_ref(peer_cfg); + break; + } + } + enumerator->destroy(enumerator); + + if (child_cfg == NULL) + { + DBG1(DBG_CFG, "no config named '%s'", msg->initiate.name); + fprintf(out, "no config named '%s'\n", msg->initiate.name); + return; + } } + charon_initiate(peer_cfg, child_cfg, msg, out); } /** @@ -470,41 +516,90 @@ METHOD(stroke_control_t, purge_ike, void, list->destroy(list); } +/** + * call charon to install a trap + */ +static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, + char *name, FILE *out) +{ + if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) + { + fprintf(out, "'%s' routed\n", name); + } + else + { + fprintf(out, "routing '%s' failed\n", name); + } +} + METHOD(stroke_control_t, route, void, private_stroke_control_t *this, stroke_msg_t *msg, FILE *out) { + child_cfg_t *child_cfg = NULL; peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; + enumerator_t *enumerator; + bool empty = TRUE; peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, msg->route.name); - if (peer_cfg == NULL) - { - fprintf(out, "no config named '%s'\n", msg->route.name); - return; - } - if (peer_cfg->get_ike_version(peer_cfg) != 2) + if (peer_cfg) { - peer_cfg->destroy(peer_cfg); - return; - } + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config", + peer_cfg->get_ike_version(peer_cfg)); + peer_cfg->destroy(peer_cfg); + return; + } - child_cfg = get_child_from_peer(peer_cfg, msg->route.name); - if (child_cfg == NULL) - { - fprintf(out, "no child config named '%s'\n", msg->route.name); - peer_cfg->destroy(peer_cfg); - return; - } + child_cfg = get_child_from_peer(peer_cfg, msg->route.name); + if (child_cfg == NULL) + { + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, &child_cfg)) + { + empty = FALSE; + charon_route(peer_cfg, child_cfg, child_cfg->get_name(child_cfg), + out); + } + enumerator->destroy(enumerator); - if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) - { - fprintf(out, "configuration '%s' routed\n", msg->route.name); + if (empty) + { + DBG1(DBG_CFG, "no child config named '%s'", msg->route.name); + fprintf(out, "no child config named '%s'\n", msg->route.name); + } + peer_cfg->destroy(peer_cfg); + return; + } } else { - fprintf(out, "routing configuration '%s' failed\n", msg->route.name); + enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends, + NULL, NULL, NULL, NULL); + while (enumerator->enumerate(enumerator, &peer_cfg)) + { + if (peer_cfg->get_ike_version(peer_cfg) != 2) + { + continue; + } + child_cfg = get_child_from_peer(peer_cfg, msg->route.name); + if (child_cfg) + { + peer_cfg->get_ref(peer_cfg); + break; + } + } + enumerator->destroy(enumerator); + + if (child_cfg == NULL) + { + DBG1(DBG_CFG, "no config named '%s'", msg->route.name); + fprintf(out, "no config named '%s'\n", msg->route.name); + return; + } } + charon_route(peer_cfg, child_cfg, msg->route.name, out); peer_cfg->destroy(peer_cfg); child_cfg->destroy(child_cfg); } diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 83e5a9ad6..baf02a6da 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -280,7 +280,7 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) chunk = crl->get_authKeyIdentifier(crl); hex = chunk_to_hex(chunk, NULL, FALSE); - snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex); + snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex.ptr); free(hex.ptr); if (cert->get_encoding(cert, CERT_ASN1_DER, &chunk)) @@ -518,7 +518,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr); return FALSE; } - snprintf(smartcard, sizeof(smartcard), "%.*s", sc.len, sc.ptr); + snprintf(smartcard, sizeof(smartcard), "%.*s", (int)sc.len, sc.ptr); smartcard[sizeof(smartcard) - 1] = '\0'; /* parse slot and key id. Three formats are supported: @@ -536,7 +536,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr, return FALSE; } *pos = '\0'; - strcpy(keyid, pos + 1); + strncpy(keyid, pos + 1, sizeof(keyid)); format = SC_FORMAT_SLOT_MODULE_KEYID; } else if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2) @@ -660,13 +660,13 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr, if (*filename.ptr == '/') { /* absolute path name */ - snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr); + snprintf(path, sizeof(path), "%.*s", (int)filename.len, filename.ptr); } else { /* relative path name */ snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, - filename.len, filename.ptr); + (int)filename.len, filename.ptr); } /* check for optional passphrase */ @@ -768,6 +768,8 @@ static bool load_shared(private_stroke_cred_t *this, chunk_t line, int line_nr, if (ugh != NULL) { DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); + shared_key->destroy(shared_key); + owners->destroy_offset(owners, offsetof(identification_t, destroy)); return FALSE; } if (id.len == 0) @@ -874,7 +876,8 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, DBG1(DBG_CFG, "include pattern too long, ignored"); continue; } - snprintf(pattern, sizeof(pattern), "%.*s", line.len, line.ptr); + snprintf(pattern, sizeof(pattern), "%.*s", + (int)line.len, line.ptr); } else { /* use directory of current file if relative */ @@ -888,7 +891,7 @@ static void load_secrets(private_stroke_cred_t *this, char *file, int level, continue; } snprintf(pattern, sizeof(pattern), "%s/%.*s", - dir, line.len, line.ptr); + dir, (int)line.len, line.ptr); free(dir); } if (glob(pattern, GLOB_ERR, NULL, &buf) != 0) diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 36311f092..6c42f8f8a 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -402,7 +402,8 @@ METHOD(stroke_list_t, status, void, if (all) { peer_cfg_t *peer_cfg; - char *plugin, *pool; + plugin_t *plugin; + char *pool; host_t *host; u_int32_t dpd; time_t since, now; @@ -431,7 +432,7 @@ METHOD(stroke_list_t, status, void, enumerator = lib->plugins->create_plugin_enumerator(lib->plugins); while (enumerator->enumerate(enumerator, &plugin)) { - fprintf(out, "%s ", plugin); + fprintf(out, "%s ", plugin->get_name(plugin)); } enumerator->destroy(enumerator); fprintf(out, "\n"); @@ -1069,12 +1070,12 @@ static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type, { char alg_name[BUF_LEN]; int alg_name_len; - + alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name); if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE) { fprintf(out, "\n "); - *len = 13; + *len = 13; } fprintf(out, "%s", alg_name); *len += alg_name_len; diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c index 2e83d0d28..2884db4bf 100644 --- a/src/libcharon/plugins/stroke/stroke_plugin.c +++ b/src/libcharon/plugins/stroke/stroke_plugin.c @@ -36,6 +36,12 @@ struct private_stroke_plugin_t { stroke_socket_t *socket; }; +METHOD(plugin_t, get_name, char*, + private_stroke_plugin_t *this) +{ + return "stroke"; +} + METHOD(plugin_t, destroy, void, private_stroke_plugin_t *this) { @@ -53,6 +59,8 @@ plugin_t *stroke_plugin_create() INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 18e77905d..88d0270d8 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -122,7 +122,7 @@ static void pop_string(stroke_msg_t *msg, char **string) /* check for sanity of string pointer and string */ if (string < (char**)msg || - string > (char**)msg + sizeof(stroke_msg_t) || + string > (char**)((char*)msg + sizeof(stroke_msg_t)) || (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) || (unsigned long)*string > msg->length) { @@ -396,7 +396,7 @@ static void stroke_export(private_stroke_socket_t *this, { if (cert->get_encoding(cert, CERT_PEM, &encoded)) { - fprintf(out, "%.*s", encoded.len, encoded.ptr); + fprintf(out, "%.*s", (int)encoded.len, encoded.ptr); free(encoded.ptr); } } diff --git a/src/libcharon/plugins/tnc_imc/Makefile.in b/src/libcharon/plugins/tnc_imc/Makefile.in index dc44408ff..c2bc35dc5 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.in +++ b/src/libcharon/plugins/tnc_imc/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc.c b/src/libcharon/plugins/tnc_imc/tnc_imc.c index 174084436..d7fc2c65d 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc.c @@ -19,11 +19,12 @@ #include <debug.h> #include <library.h> +#include <threading/mutex.h> typedef struct private_tnc_imc_t private_tnc_imc_t; /** - * Private data of an imv_t object. + * Private data of an imc_t object. */ struct private_tnc_imc_t { @@ -61,6 +62,11 @@ struct private_tnc_imc_t { * Number of supported message types */ TNC_UInt32 type_count; + + /** + * mutex to lock the imc_t object + */ + mutex_t *mutex; }; METHOD(imc_t, set_id, void, @@ -85,6 +91,14 @@ METHOD(imc_t, set_message_types, void, private_tnc_imc_t *this, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { + char buf[512]; + char *pos = buf; + int len = sizeof(buf); + int written; + + /* lock the imc_t instance */ + this->mutex->lock(this->mutex); + /* Free an existing MessageType list */ free(this->supported_types); this->supported_types = NULL; @@ -94,11 +108,27 @@ METHOD(imc_t, set_message_types, void, if (type_count && supported_types) { size_t size = type_count * sizeof(TNC_MessageType); + int i; + for (i = 0; i < type_count; i++) + { + written = snprintf(pos, len, " 0x%08x", supported_types[i]); + if (written >= len) + { + break; + } + pos += written; + len -= written; + } this->supported_types = malloc(size); memcpy(this->supported_types, supported_types, size); } - DBG2(DBG_TNC, "IMC %u supports %u message types", this->id, type_count); + *pos = '\0'; + DBG2(DBG_TNC, "IMC %u supports %u message types:%s", + this->id, type_count, buf); + + /* lock the imc_t instance */ + this->mutex->unlock(this->mutex); } METHOD(imc_t, type_supported, bool, @@ -132,6 +162,7 @@ METHOD(imc_t, destroy, void, private_tnc_imc_t *this) { dlclose(this->handle); + this->mutex->destroy(this->mutex); free(this->supported_types); free(this->name); free(this->path); @@ -156,6 +187,7 @@ imc_t* tnc_imc_create(char *name, char *path) }, .name = name, .path = path, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); this->handle = dlopen(path, RTLD_LAZY); diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c index e18f1b006..25a6a1cc4 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_bind_function.c @@ -28,6 +28,12 @@ TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { + if (!charon->imcs->is_registered(charon->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->imcs->set_message_types(charon->imcs, imc_id, supported_types, type_count); } @@ -39,6 +45,12 @@ TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id, TNC_ConnectionID connection_id, TNC_RetryReason reason) { + if (!charon->imcs->is_registered(charon->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->request_handshake_retry(charon->tnccs, TRUE, imc_id, connection_id, reason); } @@ -52,6 +64,12 @@ TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id, TNC_UInt32 msg_len, TNC_MessageType msg_type) { + if (!charon->imcs->is_registered(charon->imcs, imc_id)) + { + DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMC %u", + imc_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->send_message(charon->tnccs, imc_id, TNC_IMVID_ANY, connection_id, msg, msg_len, msg_type); } diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c index aa20534f5..ccf6aea67 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_manager.c @@ -77,7 +77,7 @@ METHOD(imc_manager_t, remove_, imc_t*, private_tnc_imc_manager_t *this, TNC_IMCID id) { enumerator_t *enumerator; - imc_t *imc; + imc_t *imc, *removed_imc = NULL; enumerator = this->imcs->create_enumerator(this->imcs); while (enumerator->enumerate(enumerator, &imc)) @@ -85,11 +85,34 @@ METHOD(imc_manager_t, remove_, imc_t*, if (id == imc->get_id(imc)) { this->imcs->remove_at(this->imcs, enumerator); - return imc; + removed_imc = imc; + break; + } + } + enumerator->destroy(enumerator); + + return removed_imc; +} + +METHOD(imc_manager_t, is_registered, bool, + private_tnc_imc_manager_t *this, TNC_IMCID id) +{ + enumerator_t *enumerator; + imc_t *imc; + bool found = FALSE; + + enumerator = this->imcs->create_enumerator(this->imcs); + while (enumerator->enumerate(enumerator, &imc)) + { + if (id == imc->get_id(imc)) + { + found = TRUE; + break; } } enumerator->destroy(enumerator); - return NULL; + + return found; } METHOD(imc_manager_t, get_preferred_language, char*, @@ -160,6 +183,7 @@ METHOD(imc_manager_t, receive_message, void, TNC_UInt32 message_len, TNC_MessageType message_type) { + bool type_supported = FALSE; enumerator_t *enumerator; imc_t *imc; @@ -168,11 +192,16 @@ METHOD(imc_manager_t, receive_message, void, { if (imc->receive_message && imc->type_supported(imc, message_type)) { + type_supported = TRUE; imc->receive_message(imc->get_id(imc), connection_id, message, message_len, message_type); } } enumerator->destroy(enumerator); + if (!type_supported) + { + DBG2(DBG_TNC, "message type 0x%08x not supported by any IMC", message_type); + } } METHOD(imc_manager_t, batch_ending, void, @@ -222,6 +251,7 @@ imc_manager_t* tnc_imc_manager_create(void) .public = { .add = _add, .remove = _remove_, /* avoid name conflict with stdio.h */ + .is_registered = _is_registered, .get_preferred_language = _get_preferred_language, .notify_connection_change = _notify_connection_change, .begin_handshake = _begin_handshake, diff --git a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c index 89888040a..bc13b8735 100644 --- a/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c +++ b/src/libcharon/plugins/tnc_imc/tnc_imc_plugin.c @@ -130,6 +130,12 @@ static bool load_imcs(char *filename) } if (!charon->imcs->add(charon->imcs, imc)) { + if (imc->terminate && + imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully", + imc->get_name(imc)); + } imc->destroy(imc); return FALSE; } @@ -141,6 +147,12 @@ static bool load_imcs(char *filename) return TRUE; } +METHOD(plugin_t, get_name, char*, + tnc_imc_plugin_t *this) +{ + return "tnc-imc"; +} + METHOD(plugin_t, destroy, void, tnc_imc_plugin_t *this) { @@ -158,6 +170,8 @@ plugin_t *tnc_imc_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/tnc_imv/Makefile.in b/src/libcharon/plugins/tnc_imv/Makefile.in index 0324d2eb9..fb96150f4 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.in +++ b/src/libcharon/plugins/tnc_imv/Makefile.in @@ -244,6 +244,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -267,6 +269,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv.c b/src/libcharon/plugins/tnc_imv/tnc_imv.c index f88b645d6..fe628ee7e 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv.c @@ -19,6 +19,7 @@ #include <debug.h> #include <library.h> +#include <threading/mutex.h> typedef struct private_tnc_imv_t private_tnc_imv_t; @@ -61,6 +62,11 @@ struct private_tnc_imv_t { * Number of supported message types */ TNC_UInt32 type_count; + + /** + * mutex to lock the imv_t object + */ + mutex_t *mutex; }; METHOD(imv_t, set_id, void, @@ -85,6 +91,14 @@ METHOD(imv_t, set_message_types, void, private_tnc_imv_t *this, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { + char buf[512]; + char *pos = buf; + int len = sizeof(buf); + int written; + + /* lock the imv_t instance */ + this->mutex->lock(this->mutex); + /* Free an existing MessageType list */ free(this->supported_types); this->supported_types = NULL; @@ -95,10 +109,27 @@ METHOD(imv_t, set_message_types, void, { size_t size = type_count * sizeof(TNC_MessageType); + int i; + + for (i = 0; i < type_count; i++) + { + written = snprintf(pos, len, " 0x%08x", supported_types[i]); + if (written >= len) + { + break; + } + pos += written; + len -= written; + } this->supported_types = malloc(size); memcpy(this->supported_types, supported_types, size); } - DBG2(DBG_TNC, "IMV %u supports %u message types", this->id, type_count); + *pos = '\0'; + DBG2(DBG_TNC, "IMV %u supports %u message types:%s", + this->id, type_count, buf); + + /* lock the imv_t instance */ + this->mutex->unlock(this->mutex); } METHOD(imv_t, type_supported, bool, @@ -132,6 +163,7 @@ METHOD(imv_t, destroy, void, private_tnc_imv_t *this) { dlclose(this->handle); + this->mutex->destroy(this->mutex); free(this->supported_types); free(this->name); free(this->path); @@ -156,6 +188,7 @@ imv_t* tnc_imv_create(char *name, char *path) }, .name = name, .path = path, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); this->handle = dlopen(path, RTLD_LAZY); diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c index 0ea52f08e..0ed00b001 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_bind_function.c @@ -28,6 +28,12 @@ TNC_Result TNC_TNCS_ReportMessageTypes(TNC_IMVID imv_id, TNC_MessageTypeList supported_types, TNC_UInt32 type_count) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring ReportMessageTypes() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->imvs->set_message_types(charon->imvs, imv_id, supported_types, type_count); } @@ -39,6 +45,12 @@ TNC_Result TNC_TNCS_RequestHandshakeRetry(TNC_IMVID imv_id, TNC_ConnectionID connection_id, TNC_RetryReason reason) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring RequestHandshakeRetry() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->request_handshake_retry(charon->tnccs, FALSE, imv_id, connection_id, reason); } @@ -52,6 +64,12 @@ TNC_Result TNC_TNCS_SendMessage(TNC_IMVID imv_id, TNC_UInt32 msg_len, TNC_MessageType msg_type) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring SendMessage() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->send_message(charon->tnccs, TNC_IMCID_ANY, imv_id, connection_id, msg, msg_len, msg_type); } @@ -65,6 +83,12 @@ TNC_Result TNC_TNCS_ProvideRecommendation(TNC_IMVID imv_id, TNC_IMV_Action_Recommendation recommendation, TNC_IMV_Evaluation_Result evaluation) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring ProvideRecommendation() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->provide_recommendation(charon->tnccs, imv_id, connection_id, recommendation, evaluation); } @@ -80,6 +104,12 @@ TNC_Result TNC_TNCS_GetAttribute(TNC_IMVID imv_id, TNC_BufferReference buffer, TNC_UInt32 *out_value_len) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring GetAttribute() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->get_attribute(charon->tnccs, imv_id, connection_id, attribute_id, buffer_len, buffer, out_value_len); } @@ -94,6 +124,12 @@ TNC_Result TNC_TNCS_SetAttribute(TNC_IMVID imv_id, TNC_UInt32 buffer_len, TNC_BufferReference buffer) { + if (!charon->imvs->is_registered(charon->imvs, imv_id)) + { + DBG1(DBG_TNC, "ignoring SetAttribute() from unregistered IMV %u", + imv_id); + return TNC_RESULT_INVALID_PARAMETER; + } return charon->tnccs->set_attribute(charon->tnccs, imv_id, connection_id, attribute_id, buffer_len, buffer); } diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c index 559de86d0..579ab06ff 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_manager.c @@ -84,7 +84,7 @@ METHOD(imv_manager_t, remove_, imv_t*, private_tnc_imv_manager_t *this, TNC_IMVID id) { enumerator_t *enumerator; - imv_t *imv; + imv_t *imv, *removed_imv = NULL; enumerator = this->imvs->create_enumerator(this->imvs); while (enumerator->enumerate(enumerator, &imv)) @@ -92,11 +92,34 @@ METHOD(imv_manager_t, remove_, imv_t*, if (id == imv->get_id(imv)) { this->imvs->remove_at(this->imvs, enumerator); - return imv; + removed_imv = imv; + break; + } + } + enumerator->destroy(enumerator); + + return removed_imv; +} + +METHOD(imv_manager_t, is_registered, bool, + private_tnc_imv_manager_t *this, TNC_IMVID id) +{ + enumerator_t *enumerator; + imv_t *imv; + bool found = FALSE; + + enumerator = this->imvs->create_enumerator(this->imvs); + while (enumerator->enumerate(enumerator, &imv)) + { + if (id == imv->get_id(imv)) + { + found = TRUE; + break; } } enumerator->destroy(enumerator); - return NULL; + + return found; } METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t, @@ -112,36 +135,56 @@ METHOD(imv_manager_t, create_recommendations, recommendations_t*, } METHOD(imv_manager_t, enforce_recommendation, bool, - private_tnc_imv_manager_t *this, TNC_IMV_Action_Recommendation rec) + private_tnc_imv_manager_t *this, TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) { char *group; identification_t *id; ike_sa_t *ike_sa; auth_cfg_t *auth; + bool no_access = FALSE; + + DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'", + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); switch (rec) { case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - DBG1(DBG_TNC, "TNC recommendation is allow"); group = "allow"; break; case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - DBG1(DBG_TNC, "TNC recommendation is isolate"); group = "isolate"; break; case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: default: - DBG1(DBG_TNC, "TNC recommendation is none"); - return FALSE; + group = "no access"; + no_access = TRUE; + break; } + ike_sa = charon->bus->get_sa(charon->bus); - if (ike_sa) + if (!ike_sa) + { + DBG1(DBG_TNC, "policy enforcement point did not find IKE_SA"); + return FALSE; + } + + id = ike_sa->get_other_id(ike_sa); + DBG0(DBG_TNC, "policy enforced on peer '%Y' is '%s'", id, group); + + if (no_access) { + return FALSE; + } + else + { auth = ike_sa->get_auth_cfg(ike_sa, FALSE); id = identification_create_from_string(group); auth->add(auth, AUTH_RULE_GROUP, id); - DBG1(DBG_TNC, "TNC added group membership '%s'", group); + DBG1(DBG_TNC, "policy enforcement point added group membership '%s'", + group); } return TRUE; } @@ -208,6 +251,7 @@ METHOD(imv_manager_t, receive_message, void, TNC_UInt32 message_len, TNC_MessageType message_type) { + bool type_supported = FALSE; enumerator_t *enumerator; imv_t *imv; @@ -216,11 +260,16 @@ METHOD(imv_manager_t, receive_message, void, { if (imv->receive_message && imv->type_supported(imv, message_type)) { + type_supported = TRUE; imv->receive_message(imv->get_id(imv), connection_id, message, message_len, message_type); } } enumerator->destroy(enumerator); + if (!type_supported) + { + DBG2(DBG_TNC, "message type 0x%08x not supported by any IMV", message_type); + } } METHOD(imv_manager_t, batch_ending, void, @@ -271,6 +320,7 @@ imv_manager_t* tnc_imv_manager_create(void) .public = { .add = _add, .remove = _remove_, /* avoid name conflict with stdio.h */ + .is_registered = _is_registered, .get_recommendation_policy = _get_recommendation_policy, .create_recommendations = _create_recommendations, .enforce_recommendation = _enforce_recommendation, diff --git a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c index f238f01ea..45cf95c1b 100644 --- a/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c +++ b/src/libcharon/plugins/tnc_imv/tnc_imv_plugin.c @@ -130,6 +130,12 @@ static bool load_imvs(char *filename) } if (!charon->imvs->add(charon->imvs, imv)) { + if (imv->terminate && + imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS) + { + DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully", + imv->get_name(imv)); + } imv->destroy(imv); return FALSE; } @@ -141,6 +147,12 @@ static bool load_imvs(char *filename) return TRUE; } +METHOD(plugin_t, get_name, char*, + tnc_imv_plugin_t *this) +{ + return "tnc-imv"; +} + METHOD(plugin_t, destroy, void, tnc_imv_plugin_t *this) { @@ -158,6 +170,8 @@ plugin_t *tnc_imv_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); diff --git a/src/libcharon/plugins/tnccs_11/Makefile.in b/src/libcharon/plugins/tnccs_11/Makefile.in index 5ab7ccbca..308dd57ca 100644 --- a/src/libcharon/plugins/tnccs_11/Makefile.in +++ b/src/libcharon/plugins/tnccs_11/Makefile.in @@ -247,6 +247,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -270,6 +272,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index 2104bf401..86f1c269f 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -77,6 +77,11 @@ struct private_tnccs_11_t { bool delete_state; /** + * SendMessage() by IMC/IMV only allowed if flag is set + */ + bool send_msg; + + /** * Flag set by IMC/IMV RequestHandshakeRetry() function */ bool request_handshake_retry; @@ -87,7 +92,7 @@ struct private_tnccs_11_t { recommendations_t *recs; }; -METHOD(tnccs_t, send_msg, void, +METHOD(tnccs_t, send_msg, TNC_Result, private_tnccs_11_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, TNC_BufferReference msg, TNC_UInt32 msg_len, @@ -95,6 +100,13 @@ METHOD(tnccs_t, send_msg, void, { tnccs_msg_t *tnccs_msg; + if (!this->send_msg) + { + DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()", + this->is_server ? "IMV" : "IMC", + this->is_server ? imv_id : imc_id); + return TNC_RESULT_ILLEGAL_OPERATION; + } tnccs_msg = imc_imv_msg_create(msg_type, chunk_create(msg, msg_len)); /* adding an IMC-IMV Message to TNCCS batch */ @@ -105,6 +117,7 @@ METHOD(tnccs_t, send_msg, void, } this->batch->add_msg(this->batch, tnccs_msg); this->mutex->unlock(this->mutex); + return TNC_RESULT_SUCCESS; } /** @@ -126,6 +139,7 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) DBG2(DBG_TNC, "handling IMC_IMV message type 0x%08x", msg_type); + this->send_msg = TRUE; if (this->is_server) { charon->imvs->receive_message(charon->imvs, @@ -136,6 +150,7 @@ static void handle_message(private_tnccs_11_t *this, tnccs_msg_t *msg) charon->imcs->receive_message(charon->imcs, this->connection_id, msg_body.ptr, msg_body.len,msg_type); } + this->send_msg = FALSE; break; } case TNCCS_MSG_RECOMMENDATION: @@ -237,6 +252,8 @@ METHOD(tls_t, process, status_t, } charon->imvs->notify_connection_change(charon->imvs, this->connection_id, TNC_CONNECTION_STATE_CREATE); + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); } data = chunk_create(buf, buflen); @@ -284,6 +301,7 @@ METHOD(tls_t, process, status_t, return FAILED; } + this->send_msg = TRUE; if (this->is_server) { charon->imvs->batch_ending(charon->imvs, this->connection_id); @@ -292,6 +310,7 @@ METHOD(tls_t, process, status_t, { charon->imcs->batch_ending(charon->imcs, this->connection_id); } + this->send_msg = FALSE; } batch->destroy(batch); @@ -369,13 +388,15 @@ METHOD(tls_t, build, status_t, this->connection_id, TNC_CONNECTION_STATE_CREATE); charon->imcs->notify_connection_change(charon->imcs, this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + this->send_msg = TRUE; charon->imcs->begin_handshake(charon->imcs, this->connection_id); + this->send_msg = FALSE; } /* Do not allow any asynchronous IMCs or IMVs to add additional messages */ this->mutex->lock(this->mutex); - if (this->is_server && !this->delete_state && + if (this->recs && !this->delete_state && (!this->batch || this->fatal_error)) { check_and_build_recommendation(this); @@ -435,11 +456,7 @@ METHOD(tls_t, is_complete, bool, if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) { - DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'", - TNC_IMV_Action_Recommendation_names, rec, - TNC_IMV_Evaluation_Result_names, eval); - - return charon->imvs->enforce_recommendation(charon->imvs, rec); + return charon->imvs->enforce_recommendation(charon->imvs, rec, eval); } else { @@ -456,17 +473,8 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_11_t *this) { - if (this->is_server) - { - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_DELETE); - } - else - { - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_DELETE); - } - charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + charon->tnccs->remove_connection(charon->tnccs, this->connection_id, + this->is_server); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); free(this); diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c index 03905ca37..9ec91f006 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + tnccs_11_plugin_t *this) +{ + return "tnccs-11"; +} + METHOD(plugin_t, destroy, void, tnccs_11_plugin_t *this) { @@ -35,11 +41,13 @@ plugin_t *tnccs_11_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_1_1, + charon->tnccs->add_method(charon->tnccs, TNCCS_1_1, (tnccs_constructor_t)tnccs_11_create); return &this->plugin; diff --git a/src/libcharon/plugins/tnccs_20/Makefile.in b/src/libcharon/plugins/tnccs_20/Makefile.in index 9853be338..bbfcc2760 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.in +++ b/src/libcharon/plugins/tnccs_20/Makefile.in @@ -249,6 +249,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -272,6 +274,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c index a46dc0ab9..f0cf14ac1 100644 --- a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c @@ -107,7 +107,8 @@ METHOD(pb_tnc_state_machine_t, receive_batch, bool, } return FALSE; case PB_STATE_SERVER_WORKING: - if (!this->is_server && type == PB_BATCH_SDATA) + if (!this->is_server && (type == PB_BATCH_SDATA || + type == PB_BATCH_SRETRY)) { this->state = PB_STATE_CLIENT_WORKING; break; @@ -117,8 +118,7 @@ METHOD(pb_tnc_state_machine_t, receive_batch, bool, this->state = PB_STATE_DECIDED; break; } - if ((this->is_server && type == PB_BATCH_CRETRY) || - (!this->is_server && type == PB_BATCH_SRETRY)) + if (this->is_server && type == PB_BATCH_CRETRY) { break; } @@ -198,7 +198,8 @@ METHOD(pb_tnc_state_machine_t, send_batch, bool, } return FALSE; case PB_STATE_SERVER_WORKING: - if (this->is_server && type == PB_BATCH_SDATA) + if (this->is_server && (type == PB_BATCH_SDATA || + type == PB_BATCH_SRETRY)) { this->state = PB_STATE_CLIENT_WORKING; break; @@ -208,7 +209,7 @@ METHOD(pb_tnc_state_machine_t, send_batch, bool, this->state = PB_STATE_DECIDED; break; } - if (this->is_server && type == PB_BATCH_SRETRY) + if (!this->is_server && type == PB_BATCH_CRETRY) { break; } @@ -219,11 +220,16 @@ METHOD(pb_tnc_state_machine_t, send_batch, bool, } return FALSE; case PB_STATE_CLIENT_WORKING: - if (!this->is_server && type == PB_BATCH_CDATA) + if (!this->is_server && (type == PB_BATCH_CDATA || + type == PB_BATCH_CRETRY)) { this->state = PB_STATE_SERVER_WORKING; break; } + if (this->is_server && type == PB_BATCH_SRETRY) + { + break; + } if (type == PB_BATCH_CLOSE) { this->state = PB_STATE_END; diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index d53fd8eb7..9e2081d46 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -81,12 +81,17 @@ struct private_tnccs_20_t { bool request_handshake_retry; /** + * SendMessage() by IMC/IMV only allowed if flag is set + */ + bool send_msg; + + /** * Set of IMV recommendations (TNC Server only) */ recommendations_t *recs; }; -METHOD(tnccs_t, send_msg, void, +METHOD(tnccs_t, send_msg, TNC_Result, private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id, TNC_BufferReference msg, TNC_UInt32 msg_len, @@ -97,6 +102,14 @@ METHOD(tnccs_t, send_msg, void, pb_tnc_msg_t *pb_tnc_msg; pb_tnc_batch_type_t batch_type; + if (!this->send_msg) + { + DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()", + this->is_server ? "IMV" : "IMC", + this->is_server ? imv_id : imc_id); + return TNC_RESULT_ILLEGAL_OPERATION; + } + msg_sub_type = msg_type & TNC_SUBTYPE_ANY; msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY; @@ -119,6 +132,7 @@ METHOD(tnccs_t, send_msg, void, pb_tnc_msg->destroy(pb_tnc_msg); } this->mutex->unlock(this->mutex); + return TNC_RESULT_SUCCESS; } /** @@ -145,6 +159,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type); + this->send_msg = TRUE; if (this->is_server) { charon->imvs->receive_message(charon->imvs, @@ -155,6 +170,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) charon->imcs->receive_message(charon->imcs, this->connection_id, msg_body.ptr, msg_body.len,msg_type); } + this->send_msg = FALSE; break; } case PB_MSG_ASSESSMENT_RESULT: @@ -289,14 +305,21 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) */ static void build_retry_batch(private_tnccs_20_t *this) { + pb_tnc_batch_type_t batch_retry_type; + + batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY; if (this->batch) { + if (this->batch->get_type(this->batch) == batch_retry_type) + { + /* retry batch has already been created */ + return; + } DBG1(DBG_TNC, "cancelling PB-TNC %N batch", pb_tnc_batch_type_names, this->batch->get_type(this->batch)); this->batch->destroy(this->batch); } - this->batch = pb_tnc_batch_create(this->is_server, - this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY); + this->batch = pb_tnc_batch_create(this->is_server, batch_retry_type); } METHOD(tls_t, process, status_t, @@ -319,6 +342,8 @@ METHOD(tls_t, process, status_t, } charon->imvs->notify_connection_change(charon->imvs, this->connection_id, TNC_CONNECTION_STATE_CREATE); + charon->imvs->notify_connection_change(charon->imvs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); } data = chunk_create(buf, buflen); @@ -349,7 +374,9 @@ METHOD(tls_t, process, status_t, /* Restart the measurements */ charon->imcs->notify_connection_change(charon->imcs, this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + this->send_msg = TRUE; charon->imcs->begin_handshake(charon->imcs, this->connection_id); + this->send_msg = FALSE; } enumerator = batch->create_msg_enumerator(batch); @@ -376,6 +403,7 @@ METHOD(tls_t, process, status_t, } } + this->send_msg = TRUE; if (this->is_server) { charon->imvs->batch_ending(charon->imvs, this->connection_id); @@ -384,6 +412,7 @@ METHOD(tls_t, process, status_t, { charon->imcs->batch_ending(charon->imcs, this->connection_id); } + this->send_msg = FALSE; } switch (status) @@ -463,6 +492,7 @@ METHOD(tls_t, build, status_t, private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen) { status_t status; + pb_tnc_state_t state; /* Initialize the connection */ if (!this->is_server && !this->connection_id) @@ -491,11 +521,14 @@ METHOD(tls_t, build, status_t, this->connection_id, TNC_CONNECTION_STATE_CREATE); charon->imcs->notify_connection_change(charon->imcs, this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + this->send_msg = TRUE; charon->imcs->begin_handshake(charon->imcs, this->connection_id); + this->send_msg = FALSE; } - if (this->is_server && this->fatal_error && - this->state_machine->get_state(this->state_machine) == PB_STATE_END) + state = this->state_machine->get_state(this->state_machine); + + if (this->is_server && this->fatal_error && state == PB_STATE_END) { DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection"); return FAILED; @@ -506,7 +539,10 @@ METHOD(tls_t, build, status_t, if (this->request_handshake_retry) { - build_retry_batch(this); + if (state != PB_STATE_INIT) + { + build_retry_batch(this); + } /* Reset the flag for the next handshake retry request */ this->request_handshake_retry = FALSE; @@ -514,9 +550,6 @@ METHOD(tls_t, build, status_t, if (!this->batch) { - pb_tnc_state_t state; - - state = this->state_machine->get_state(this->state_machine); if (this->is_server) { if (state == PB_STATE_SERVER_WORKING) @@ -606,11 +639,7 @@ METHOD(tls_t, is_complete, bool, if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval)) { - DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'", - TNC_IMV_Action_Recommendation_names, rec, - TNC_IMV_Evaluation_Result_names, eval); - - return charon->imvs->enforce_recommendation(charon->imvs, rec); + return charon->imvs->enforce_recommendation(charon->imvs, rec, eval); } else { @@ -627,17 +656,8 @@ METHOD(tls_t, get_eap_msk, chunk_t, METHOD(tls_t, destroy, void, private_tnccs_20_t *this) { - if (this->is_server) - { - charon->imvs->notify_connection_change(charon->imvs, - this->connection_id, TNC_CONNECTION_STATE_DELETE); - } - else - { - charon->imcs->notify_connection_change(charon->imcs, - this->connection_id, TNC_CONNECTION_STATE_DELETE); - } - charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + charon->tnccs->remove_connection(charon->tnccs, this->connection_id, + this->is_server); this->state_machine->destroy(this->state_machine); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c index 82c78f74c..e6dc699e6 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + tnccs_20_plugin_t *this) +{ + return "tnccs-20"; +} + METHOD(plugin_t, destroy, void, tnccs_20_plugin_t *this) { @@ -35,11 +41,13 @@ plugin_t *tnccs_20_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_2_0, + charon->tnccs->add_method(charon->tnccs, TNCCS_2_0, (tnccs_constructor_t)tnccs_20_create); return &this->plugin; diff --git a/src/libcharon/plugins/tnccs_dynamic/Makefile.in b/src/libcharon/plugins/tnccs_dynamic/Makefile.in index 722da2830..dda1472db 100644 --- a/src/libcharon/plugins/tnccs_dynamic/Makefile.in +++ b/src/libcharon/plugins/tnccs_dynamic/Makefile.in @@ -245,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -268,6 +270,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c index dbbf222e0..089a3ed57 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c @@ -18,6 +18,12 @@ #include <daemon.h> +METHOD(plugin_t, get_name, char*, + tnccs_dynamic_plugin_t *this) +{ + return "tnccs-dynamic"; +} + METHOD(plugin_t, destroy, void, tnccs_dynamic_plugin_t *this) { @@ -35,11 +41,13 @@ plugin_t *tnccs_dynamic_plugin_create() INIT(this, .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, ); - charon->tnccs->add_method(charon->tnccs, TNCCS_DYNAMIC, + charon->tnccs->add_method(charon->tnccs, TNCCS_DYNAMIC, (tnccs_constructor_t)tnccs_dynamic_create); return &this->plugin; diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index f7162d800..013ceb7da 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -241,6 +241,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -264,6 +266,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c index 4790ef4e7..a6d24c32b 100644 --- a/src/libcharon/plugins/uci/uci_plugin.c +++ b/src/libcharon/plugins/uci/uci_plugin.c @@ -58,10 +58,14 @@ struct private_uci_plugin_t { uci_control_t *control; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_uci_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_uci_plugin_t *this) +{ + return "uci"; +} + +METHOD(plugin_t, destroy, void, + private_uci_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set); @@ -77,14 +81,22 @@ static void destroy(private_uci_plugin_t *this) */ plugin_t *uci_plugin_create() { - private_uci_plugin_t *this = malloc_thing(private_uci_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_uci_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .parser = uci_parser_create(UCI_PACKAGE), + .config = uci_config_create(this->parser), + .creds = uci_creds_create(this->parser), + .control = uci_control_create(), + ); - this->parser = uci_parser_create(UCI_PACKAGE); - this->config = uci_config_create(this->parser); - this->creds = uci_creds_create(this->parser); - this->control = uci_control_create(); charon->backends->add_backend(charon->backends, &this->config->backend); lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in index 5fa749e56..2fee3da82 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.in +++ b/src/libcharon/plugins/unit_tester/Makefile.in @@ -247,6 +247,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -270,6 +272,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/unit_tester/unit_tester.c b/src/libcharon/plugins/unit_tester/unit_tester.c index 5f6f94e03..ad7dba7a5 100644 --- a/src/libcharon/plugins/unit_tester/unit_tester.c +++ b/src/libcharon/plugins/unit_tester/unit_tester.c @@ -92,10 +92,14 @@ static void run_tests(private_unit_tester_t *this) success, run, failed, skipped); } -/** - * Implementation of 2007_t.destroy - */ -static void destroy(private_unit_tester_t *this) +METHOD(plugin_t, get_name, char*, + private_unit_tester_t *this) +{ + return "unit-tester"; +} + +METHOD(plugin_t, destroy, void, + private_unit_tester_t *this) { free(this); } @@ -105,9 +109,17 @@ static void destroy(private_unit_tester_t *this) */ plugin_t *unit_tester_plugin_create() { - private_unit_tester_t *this = malloc_thing(private_unit_tester_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + private_unit_tester_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + ); run_tests(this); diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index 5dd2dc843..49cffe218 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -243,6 +243,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -266,6 +268,7 @@ soup_LIBS = @soup_LIBS@ srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c index 9d0591e62..2ce2d3257 100644 --- a/src/libcharon/plugins/updown/updown_plugin.c +++ b/src/libcharon/plugins/updown/updown_plugin.c @@ -36,10 +36,14 @@ struct private_updown_plugin_t { updown_listener_t *listener; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_updown_plugin_t *this) +METHOD(plugin_t, get_name, char*, + private_updown_plugin_t *this) +{ + return "updown"; +} + +METHOD(plugin_t, destroy, void, + private_updown_plugin_t *this) { charon->bus->remove_listener(charon->bus, &this->listener->listener); this->listener->destroy(this->listener); @@ -51,11 +55,19 @@ static void destroy(private_updown_plugin_t *this) */ plugin_t *updown_plugin_create() { - private_updown_plugin_t *this = malloc_thing(private_updown_plugin_t); + private_updown_plugin_t *this; - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .listener = updown_listener_create(), + ); - this->listener = updown_listener_create(); charon->bus->add_listener(charon->bus, &this->listener->listener); return &this->public.plugin; diff --git a/src/libcharon/plugins/whitelist/Makefile.am b/src/libcharon/plugins/whitelist/Makefile.am new file mode 100644 index 000000000..064a759dd --- /dev/null +++ b/src/libcharon/plugins/whitelist/Makefile.am @@ -0,0 +1,21 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-whitelist.la +else +plugin_LTLIBRARIES = libstrongswan-whitelist.la +endif + +libstrongswan_whitelist_la_SOURCES = whitelist_plugin.h whitelist_plugin.c \ + whitelist_listener.h whitelist_listener.c whitelist_msg.h \ + whitelist_control.h whitelist_control.c + +libstrongswan_whitelist_la_LDFLAGS = -module -avoid-version + +ipsec_PROGRAMS = whitelist +whitelist_SOURCES = whitelist.c diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in new file mode 100644 index 000000000..37ae5f9c3 --- /dev/null +++ b/src/libcharon/plugins/whitelist/Makefile.in @@ -0,0 +1,668 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +ipsec_PROGRAMS = whitelist$(EXEEXT) +subdir = src/libcharon/plugins/whitelist +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ + $(top_srcdir)/m4/config/ltoptions.m4 \ + $(top_srcdir)/m4/config/ltsugar.m4 \ + $(top_srcdir)/m4/config/ltversion.m4 \ + $(top_srcdir)/m4/config/lt~obsolete.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_whitelist_la_LIBADD = +am_libstrongswan_whitelist_la_OBJECTS = whitelist_plugin.lo \ + whitelist_listener.lo whitelist_control.lo +libstrongswan_whitelist_la_OBJECTS = \ + $(am_libstrongswan_whitelist_la_OBJECTS) +libstrongswan_whitelist_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_whitelist_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_whitelist_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_whitelist_la_rpath = +PROGRAMS = $(ipsec_PROGRAMS) +am_whitelist_OBJECTS = whitelist.$(OBJEXT) +whitelist_OBJECTS = $(am_whitelist_OBJECTS) +whitelist_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libstrongswan_whitelist_la_SOURCES) $(whitelist_SOURCES) +DIST_SOURCES = $(libstrongswan_whitelist_la_SOURCES) \ + $(whitelist_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PTHREADLIB = @PTHREADLIB@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYINCLUDE = @RUBYINCLUDE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipsecuser = @ipsecuser@ +libcharon_plugins = @libcharon_plugins@ +libdir = @libdir@ +libexecdir = @libexecdir@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +openac_plugins = @openac_plugins@ +p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pluto_plugins = @pluto_plugins@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +urandom_device = @urandom_device@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic \ + -DIPSEC_PIDDIR=\"${piddir}\" + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-whitelist.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-whitelist.la +libstrongswan_whitelist_la_SOURCES = whitelist_plugin.h whitelist_plugin.c \ + whitelist_listener.h whitelist_listener.c whitelist_msg.h \ + whitelist_control.h whitelist_control.c + +libstrongswan_whitelist_la_LDFLAGS = -module -avoid-version +whitelist_SOURCES = whitelist.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/whitelist/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/whitelist/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ + } + +uninstall-pluginLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ + done + +clean-pluginLTLIBRARIES: + -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) + @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstrongswan-whitelist.la: $(libstrongswan_whitelist_la_OBJECTS) $(libstrongswan_whitelist_la_DEPENDENCIES) + $(libstrongswan_whitelist_la_LINK) $(am_libstrongswan_whitelist_la_rpath) $(libstrongswan_whitelist_la_OBJECTS) $(libstrongswan_whitelist_la_LIBADD) $(LIBS) +install-ipsecPROGRAMS: $(ipsec_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(ipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(ipsecdir)" + @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(ipsecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(ipsecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-ipsecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(ipsecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(ipsecdir)" && rm -f $$files + +clean-ipsecPROGRAMS: + @list='$(ipsec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +whitelist$(EXEEXT): $(whitelist_OBJECTS) $(whitelist_DEPENDENCIES) + @rm -f whitelist$(EXEEXT) + $(LINK) $(whitelist_OBJECTS) $(whitelist_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whitelist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whitelist_control.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whitelist_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whitelist_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(ipsecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-ipsecPROGRAMS install-pluginLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-ipsecPROGRAMS uninstall-pluginLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-ipsecPROGRAMS clean-libtool clean-noinstLTLIBRARIES \ + clean-pluginLTLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-ipsecPROGRAMS install-man \ + install-pdf install-pdf-am install-pluginLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-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. +.NOEXPORT: diff --git a/src/libcharon/plugins/whitelist/whitelist.c b/src/libcharon/plugins/whitelist/whitelist.c new file mode 100644 index 000000000..5f511f2c5 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "whitelist_msg.h" + +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stddef.h> +#include <stdio.h> +#include <errno.h> + +/** + * Connect to the daemon, return FD + */ +static int make_connection() +{ + struct sockaddr_un addr; + int fd; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, WHITELIST_SOCKET); + + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) + { + fprintf(stderr, "opening socket failed: %s\n", strerror(errno)); + return -1; + } + if (connect(fd, (struct sockaddr *)&addr, + offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) + { + fprintf(stderr, "connecting to %s failed: %s\n", + WHITELIST_SOCKET, strerror(errno)); + close(fd); + return -1; + } + return fd; +} + +/** + * Send a single message + */ +static int send_msg(int type, char *id) +{ + whitelist_msg_t msg = { + .type = type, + }; + int fd; + + fd = make_connection(); + if (fd == -1) + { + return 2; + } + snprintf(msg.id, sizeof(msg.id), "%s", id); + if (send(fd, &msg, sizeof(msg), 0) != sizeof(msg)) + { + fprintf(stderr, "writing to socket failed: %s\n", strerror(errno)); + close(fd); + return 2; + } + if (type == WHITELIST_LIST) + { + while (recv(fd, &msg, sizeof(msg), 0) == sizeof(msg)) + { + if (msg.type != WHITELIST_LIST) + { + break; + } + printf("%s\n", msg.id); + } + } + close(fd); + return 0; +} + +/** + * Send a batch of messages, reading identities from a file + */ +static int send_batch(int type, char *file) +{ + whitelist_msg_t msg = { + .type = type, + }; + FILE *f = stdin; + int fd, len; + + fd = make_connection(); + if (fd == -1) + { + return 2; + } + if (file) + { + f = fopen(file, "r"); + if (f == NULL) + { + fprintf(stderr, "opening %s failed: %s\n", file, strerror(errno)); + close(fd); + return 3; + } + } + while (fgets(msg.id, sizeof(msg.id), f)) + { + len = strlen(msg.id); + if (len == 0) + { + continue; + } + if (msg.id[len-1] == '\n') + { + msg.id[len-1] = '\0'; + } + if (send(fd, &msg, sizeof(msg), 0) != sizeof(msg)) + { + fprintf(stderr, "writing to socket failed: %s\n", strerror(errno)); + if (f != stdin) + { + fclose(f); + } + close(fd); + return 2; + } + } + if (f != stdin) + { + fclose(f); + } + close(fd); + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc == 3 && strcmp(argv[1], "add") == 0) + { + return send_msg(WHITELIST_ADD, argv[2]); + } + if (argc == 3 && strcmp(argv[1], "remove") == 0) + { + return send_msg(WHITELIST_REMOVE, argv[2]); + } + if ((argc == 2 || argc == 3) && strcmp(argv[1], "add-from") == 0) + { + return send_batch(WHITELIST_ADD, argc == 3 ? argv[2] : NULL); + } + if ((argc == 2 || argc == 3) && strcmp(argv[1], "remove-from") == 0) + { + return send_batch(WHITELIST_REMOVE, argc == 3 ? argv[2] : NULL); + } + if ((argc == 2 || argc == 3) && strcmp(argv[1], "flush") == 0) + { + return send_msg(WHITELIST_FLUSH, argc == 3 ? argv[2] : "%any"); + } + if ((argc == 2 || argc == 3) && strcmp(argv[1], "list") == 0) + { + return send_msg(WHITELIST_LIST, argc == 3 ? argv[2] : "%any"); + } + if (argc == 2 && strcmp(argv[1], "enable") == 0) + { + return send_msg(WHITELIST_ENABLE, ""); + } + if (argc == 2 && strcmp(argv[1], "disable") == 0) + { + return send_msg(WHITELIST_DISABLE, ""); + } + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s add <identity>\n", argv[0]); + fprintf(stderr, " %s remove <identity>\n", argv[0]); + fprintf(stderr, " %s add-from <file>\n", argv[0]); + fprintf(stderr, " %s remove-from <file>\n", argv[0]); + fprintf(stderr, " %s flush [<pattern>]\n", argv[0]); + fprintf(stderr, " %s list [<pattern>]\n", argv[0]); + fprintf(stderr, " %s enable\n", argv[0]); + fprintf(stderr, " %s disable\n", argv[0]); + return 1; +} diff --git a/src/libcharon/plugins/whitelist/whitelist_control.c b/src/libcharon/plugins/whitelist/whitelist_control.c new file mode 100644 index 000000000..4a1fc5d87 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_control.c @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "whitelist_control.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <errno.h> + +#include <daemon.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> + +#include "whitelist_msg.h" + +typedef struct private_whitelist_control_t private_whitelist_control_t; + +/** + * Private data of an whitelist_control_t object. + */ +struct private_whitelist_control_t { + + /** + * Public whitelist_control_t interface. + */ + whitelist_control_t public; + + /** + * Whitelist + */ + whitelist_listener_t *listener; + + /** + * Whitelist unix socket file descriptor + */ + int socket; + + /** + * Callback job dispatching commands + */ + callback_job_t *job; +}; + +/** + * Open whitelist unix socket + */ +static bool open_socket(private_whitelist_control_t *this) +{ + struct sockaddr_un addr; + mode_t old; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, WHITELIST_SOCKET); + + this->socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (this->socket == -1) + { + DBG1(DBG_CFG, "creating whitelist socket failed"); + return FALSE; + } + unlink(addr.sun_path); + old = umask(~(S_IRWXU | S_IRWXG)); + if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { + DBG1(DBG_CFG, "binding whitelist socket failed: %s", strerror(errno)); + close(this->socket); + return FALSE; + } + umask(old); + if (chown(addr.sun_path, charon->uid, charon->gid) != 0) + { + DBG1(DBG_CFG, "changing whitelist socket permissions failed: %s", + strerror(errno)); + } + if (listen(this->socket, 10) < 0) + { + DBG1(DBG_CFG, "listening on whitelist socket failed: %s", strerror(errno)); + close(this->socket); + unlink(addr.sun_path); + return FALSE; + } + return TRUE; +} + +/** + * Dispatch a received message + */ +static void dispatch(private_whitelist_control_t *this, + int fd, whitelist_msg_t *msg) +{ + identification_t *id, *current; + enumerator_t *enumerator; + + msg->id[sizeof(msg->id)-1] = 0; + id = identification_create_from_string(msg->id); + switch (msg->type) + { + case WHITELIST_ADD: + this->listener->add(this->listener, id); + break; + case WHITELIST_REMOVE: + this->listener->remove(this->listener, id); + break; + case WHITELIST_LIST: + enumerator = this->listener->create_enumerator(this->listener); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->matches(current, id)) + { + snprintf(msg->id, sizeof(msg->id), "%Y", current); + if (send(fd, msg, sizeof(*msg), 0) != sizeof(*msg)) + { + DBG1(DBG_CFG, "listing whitelist failed"); + break; + } + } + } + enumerator->destroy(enumerator); + msg->type = WHITELIST_END; + memset(msg->id, 0, sizeof(msg->id)); + send(fd, msg, sizeof(*msg), 0); + break; + case WHITELIST_FLUSH: + this->listener->flush(this->listener, id); + break; + case WHITELIST_ENABLE: + this->listener->set_active(this->listener, TRUE); + break; + case WHITELIST_DISABLE: + this->listener->set_active(this->listener, FALSE); + break; + default: + DBG1(DBG_CFG, "received unknown whitelist command"); + break; + } + id->destroy(id); +} + +/** + * Accept whitelist control connections, dispatch + */ +static job_requeue_t receive(private_whitelist_control_t *this) +{ + struct sockaddr_un addr; + int fd, len = sizeof(addr); + whitelist_msg_t msg; + bool oldstate; + + oldstate = thread_cancelability(TRUE); + fd = accept(this->socket, (struct sockaddr*)&addr, &len); + thread_cancelability(oldstate); + + if (fd != -1) + { + while (TRUE) + { + oldstate = thread_cancelability(TRUE); + len = recv(fd, &msg, sizeof(msg), 0); + thread_cancelability(oldstate); + + if (len == sizeof(msg)) + { + dispatch(this, fd, &msg); + } + else + { + if (len != 0) + { + DBG1(DBG_CFG, "receiving whitelist msg failed: %s", + strerror(errno)); + } + break; + } + } + close(fd); + } + else + { + DBG1(DBG_CFG, "accepting whitelist connection failed: %s", + strerror(errno)); + } + return JOB_REQUEUE_FAIR; +} + +METHOD(whitelist_control_t, destroy, void, + private_whitelist_control_t *this) +{ + this->job->cancel(this->job); + close(this->socket); + free(this); +} + +/** + * See header + */ +whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener) +{ + private_whitelist_control_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .listener = listener, + ); + + if (!open_socket(this)) + { + free(this); + return NULL; + } + + this->job = callback_job_create((callback_job_cb_t)receive, + this, NULL, NULL); + lib->processor->queue_job(lib->processor, (job_t*)this->job); + + return &this->public; +} diff --git a/src/libcharon/plugins/whitelist/whitelist_control.h b/src/libcharon/plugins/whitelist/whitelist_control.h new file mode 100644 index 000000000..dc813414d --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_control.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup whitelist_control whitelist_control + * @{ @ingroup whitelist + */ + +#ifndef WHITELIST_CONTROL_H_ +#define WHITELIST_CONTROL_H_ + +#include "whitelist_listener.h" + +typedef struct whitelist_control_t whitelist_control_t; + +/** + * Whitelist UNIX control socket. + */ +struct whitelist_control_t { + + /** + * Destroy a whitelist_control_t. + */ + void (*destroy)(whitelist_control_t *this); +}; + +/** + * Create a whitelist_control instance. + */ +whitelist_control_t *whitelist_control_create(whitelist_listener_t *listener); + +#endif /** WHITELIST_CONTROL_H_ @}*/ diff --git a/src/libcharon/plugins/whitelist/whitelist_listener.c b/src/libcharon/plugins/whitelist/whitelist_listener.c new file mode 100644 index 000000000..5634e3ef8 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_listener.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "whitelist_listener.h" + +#include <daemon.h> +#include <utils/hashtable.h> +#include <threading/rwlock.h> + +typedef struct private_whitelist_listener_t private_whitelist_listener_t; + +/** + * Private data of an whitelist_listener_t object. + */ +struct private_whitelist_listener_t { + + /** + * Public whitelist_listener_t interface. + */ + whitelist_listener_t public; + + /** + * Lock for hashtable + */ + rwlock_t *lock; + + /** + * Hashtable with whitelisted identities + */ + hashtable_t *ids; + + /** + * Whitelist checking enabled + */ + bool enabled; +}; + +/** + * Hashtable hash function + */ +static u_int hash(identification_t *key) +{ + return chunk_hash(key->get_encoding(key)); +} + +/** + * Hashtable equals function + */ +static bool equals(identification_t *a, identification_t *b) +{ + return a->equals(a, b); +} + +METHOD(listener_t, authorize, bool, + private_whitelist_listener_t *this, ike_sa_t *ike_sa, + bool final, bool *success) +{ + /* check each authentication round */ + if (this->enabled && !final) + { + bool whitelisted = FALSE; + identification_t *id; + auth_cfg_t *auth; + + auth = ike_sa->get_auth_cfg(ike_sa, FALSE); + /* for authenticated with EAP, check EAP identity */ + id = auth->get(auth, AUTH_RULE_EAP_IDENTITY); + if (!id) + { + id = auth->get(auth, AUTH_RULE_IDENTITY); + } + if (id) + { + this->lock->read_lock(this->lock); + whitelisted = this->ids->get(this->ids, id) != NULL; + this->lock->unlock(this->lock); + } + if (whitelisted) + { + DBG2(DBG_CFG, "peer identity '%Y' whitelisted", id); + } + else + { + DBG1(DBG_CFG, "peer identity '%Y' not whitelisted", id); + *success = FALSE; + } + } + return TRUE; +} + +METHOD(whitelist_listener_t, add, void, + private_whitelist_listener_t *this, identification_t *id) +{ + id = id->clone(id); + this->lock->write_lock(this->lock); + id = this->ids->put(this->ids, id, id); + this->lock->unlock(this->lock); + DESTROY_IF(id); +} + +METHOD(whitelist_listener_t, remove_, void, + private_whitelist_listener_t *this, identification_t *id) +{ + this->lock->write_lock(this->lock); + id = this->ids->remove(this->ids, id); + this->lock->unlock(this->lock); + DESTROY_IF(id); +} + +/** + * Enumerator filter, from hashtable (key, value) to single identity + */ +static bool whitelist_filter(rwlock_t *lock, identification_t **key, + identification_t **id, identification_t **value) +{ + *id = *value; + return TRUE; +} + +METHOD(whitelist_listener_t, create_enumerator, enumerator_t*, + private_whitelist_listener_t *this) +{ + this->lock->read_lock(this->lock); + return enumerator_create_filter(this->ids->create_enumerator(this->ids), + (void*)whitelist_filter, this->lock, + (void*)this->lock->unlock); +} + +METHOD(whitelist_listener_t, flush, void, + private_whitelist_listener_t *this, identification_t *id) +{ + enumerator_t *enumerator; + identification_t *key, *value; + + this->lock->write_lock(this->lock); + enumerator = this->ids->create_enumerator(this->ids); + while (enumerator->enumerate(enumerator, &key, &value)) + { + if (value->matches(value, id)) + { + this->ids->remove_at(this->ids, enumerator); + value->destroy(value); + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +METHOD(whitelist_listener_t, set_active, void, + private_whitelist_listener_t *this, bool enable) +{ + DBG1(DBG_CFG, "whitelist functionality %s%sabled", + (this->enabled == enable) ? "was already " : "", enable ? "en" : "dis"); + this->enabled = enable; +} + +METHOD(whitelist_listener_t, destroy, void, + private_whitelist_listener_t *this) +{ + identification_t *key, *value; + enumerator_t *enumerator; + + enumerator = this->ids->create_enumerator(this->ids); + while (enumerator->enumerate(enumerator, &key, &value)) + { + value->destroy(value); + } + enumerator->destroy(enumerator); + this->ids->destroy(this->ids); + this->lock->destroy(this->lock); + free(this); +} + +/** + * See header + */ +whitelist_listener_t *whitelist_listener_create() +{ + private_whitelist_listener_t *this; + + INIT(this, + .public = { + .listener = { + .authorize = _authorize, + }, + .add = _add, + .remove = _remove_, + .create_enumerator = _create_enumerator, + .flush = _flush, + .set_active = _set_active, + .destroy = _destroy, + }, + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .ids = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 32), + .enabled = lib->settings->get_bool(lib->settings, + "charon.plugins.whitelist.enable", FALSE), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/whitelist/whitelist_listener.h b/src/libcharon/plugins/whitelist/whitelist_listener.h new file mode 100644 index 000000000..ac9475245 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_listener.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup whitelist_listener whitelist_listener + * @{ @ingroup whitelist + */ + +#ifndef WHITELIST_LISTENER_H_ +#define WHITELIST_LISTENER_H_ + +#include <bus/listeners/listener.h> + +typedef struct whitelist_listener_t whitelist_listener_t; + +/** + * Listener checking connecting peer against a whitelist. + */ +struct whitelist_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Add a peer identity to the whitelist. + * + * @param id identity to whitelist + */ + void (*add)(whitelist_listener_t *this, identification_t *id); + + /** + * Remove a peer identity from the whitelist. + * + * @param id identity to remove from whitelist + */ + void (*remove)(whitelist_listener_t *this, identification_t *id); + + /** + * Create an enumerator over whitelisted peer identities. + * + * The enumerator read-locks the whitelist, do not call add/remove while + * it is alive. + * + * @return enumerator over identification_t* + */ + enumerator_t* (*create_enumerator)(whitelist_listener_t *this); + + /** + * Flush identities from whitelist matching id. + * + * @param id id to match + */ + void (*flush)(whitelist_listener_t *this, identification_t *id); + + /** + * Enable/Disable whitelist checking. + * + * @param enable TRUE to enable, FALSE to disable + */ + void (*set_active)(whitelist_listener_t *this, bool enable); + + /** + * Destroy a whitelist_listener_t. + */ + void (*destroy)(whitelist_listener_t *this); +}; + +/** + * Create a whitelist_listener instance. + */ +whitelist_listener_t *whitelist_listener_create(); + +#endif /** WHITELIST_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/whitelist/whitelist_msg.h b/src/libcharon/plugins/whitelist/whitelist_msg.h new file mode 100644 index 000000000..65b922996 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_msg.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup whitelist_msg whitelist_msg + * @{ @ingroup whitelist + */ + +#ifndef WHITELIST_MSG_H_ +#define WHITELIST_MSG_H_ + +#define WHITELIST_SOCKET IPSEC_PIDDIR "/charon.wlst" + +typedef struct whitelist_msg_t whitelist_msg_t; + +/** + * Message type. + */ +enum { + /* add whitelist entry */ + WHITELIST_ADD = 1, + /* remove whitelist entry */ + WHITELIST_REMOVE = 2, + /* list identities matching id, gets responded with LIST messages */ + WHITELIST_LIST = 3, + /* indicates end of list in a series of LIST messages */ + WHITELIST_END = 4, + /* flush identities matching id */ + WHITELIST_FLUSH = 5, + /* enable whitelist checking */ + WHITELIST_ENABLE = 6, + /* disable whitelist checking */ + WHITELIST_DISABLE = 7, +}; + +/** + * Message to exchange over whitelist + */ +struct whitelist_msg_t { + /** message type */ + int type; + /** null terminated identity */ + char id[128]; +}; + +#endif /** WHITELIST_MSG_H_ @}*/ diff --git a/src/libcharon/plugins/whitelist/whitelist_plugin.c b/src/libcharon/plugins/whitelist/whitelist_plugin.c new file mode 100644 index 000000000..fca9d293f --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_plugin.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "whitelist_plugin.h" + +#include "whitelist_listener.h" +#include "whitelist_control.h" + +#include <daemon.h> + +typedef struct private_whitelist_plugin_t private_whitelist_plugin_t; + +/** + * private data of whitelist plugin + */ +struct private_whitelist_plugin_t { + + /** + * implements plugin interface + */ + whitelist_plugin_t public; + + /** + * Listener checking whitelist entries during authorization + */ + whitelist_listener_t *listener; + + /** + * Whitelist control socket + */ + whitelist_control_t *control; +}; + +METHOD(plugin_t, get_name, char*, + private_whitelist_plugin_t *this) +{ + return "whitelist"; +} + +METHOD(plugin_t, destroy, void, + private_whitelist_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->listener->destroy(this->listener); + DESTROY_IF(this->control); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *whitelist_plugin_create() +{ + private_whitelist_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .listener = whitelist_listener_create(), + ); + this->control = whitelist_control_create(this->listener); + + charon->bus->add_listener(charon->bus, &this->listener->listener); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/whitelist/whitelist_plugin.h b/src/libcharon/plugins/whitelist/whitelist_plugin.h new file mode 100644 index 000000000..243313376 --- /dev/null +++ b/src/libcharon/plugins/whitelist/whitelist_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 Martin Willi + * Copyright (C) 2011 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup whitelist whitelist + * @ingroup cplugins + * + * @defgroup whitelist_plugin whitelist_plugin + * @{ @ingroup whitelist + */ + +#ifndef WHITELIST_PLUGIN_H_ +#define WHITELIST_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct whitelist_plugin_t whitelist_plugin_t; + +/** + * Peer identity whitelisting plugin. + */ +struct whitelist_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** WHITELIST_PLUGIN_H_ @}*/ diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c index da3ecf06f..468c9ef94 100644 --- a/src/libcharon/processing/jobs/delete_ike_sa_job.c +++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c @@ -76,8 +76,8 @@ METHOD(job_t, execute, void, } else { - /* destroy only if not ESTABLISHED */ - if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED) + /* destroy IKE_SA did not complete connecting phase */ + if (ike_sa->get_state(ike_sa) != IKE_CONNECTING) { charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h index 9961039ff..0eab2b5ff 100644 --- a/src/libcharon/sa/authenticators/eap/eap_method.h +++ b/src/libcharon/sa/authenticators/eap/eap_method.h @@ -113,14 +113,29 @@ struct eap_method_t { * Not all EAP methods establish a shared secret. For implementations of * the EAP-Identity method, get_msk() returns the received identity. * - * @param msk chunk receiving internal stored MSK + * @param msk chunk receiving internal stored MSK * @return - * - SUCCESS, or - * - FAILED, if MSK not established (yet) + * - SUCCESS, or + * - FAILED, if MSK not established (yet) */ status_t (*get_msk) (eap_method_t *this, chunk_t *msk); /** + * Get the current EAP identifier. + * + * @return current EAP identifier + */ + u_int8_t (*get_identifier) (eap_method_t *this); + + /** + * Set the EAP identifier to a deterministic value, overwriting + * the randomly initialized default value. + * + * @param identifier current EAP identifier + */ + void (*set_identifier) (eap_method_t *this, u_int8_t identifier); + + /** * Destroys a eap_method_t object. */ void (*destroy) (eap_method_t *this); diff --git a/src/libcharon/sa/authenticators/eap/sim_card.h b/src/libcharon/sa/authenticators/eap/sim_card.h new file mode 100644 index 000000000..5f5dc580b --- /dev/null +++ b/src/libcharon/sa/authenticators/eap/sim_card.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sim_card sim_card + * @{ @ingroup eap + */ + +#ifndef SIM_CARD_H_ +#define SIM_CARD_H_ + +typedef struct sim_card_t sim_card_t; + +/** + * Interface for a (U)SIM card (used as EAP client). + * + * The SIM card completes triplets/quintuplets requested in a challenge + * received from the server. + * An implementation supporting only one of SIM/AKA authentication may + * implement the other methods with return_false()/return NOT_SUPPORTED/NULL. + */ +struct sim_card_t { + + /** + * Calculate SRES/KC from a RAND for SIM authentication. + * + * @param id permanent identity to get a triplet for + * @param rand RAND input buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if SRES/KC calculated, FALSE on error/wrong identity + */ + bool (*get_triplet)(sim_card_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], + char kc[SIM_KC_LEN]); + + /** + * Calculate CK/IK/RES from RAND/AUTN for AKA authentication. + * + * If the received sequence number (in autn) is out of sync, INVALID_STATE + * is returned. + * The RES value is the only one with variable length. Pass a buffer + * of at least AKA_RES_MAX, the actual number of bytes is written to the + * res_len value. While the standard would allow any bit length between + * 32 and 128 bits, we support only full bytes for now. + * + * @param id permanent identity to request quintuplet for + * @param rand random value rand + * @param autn authentication token autn + * @param ck buffer receiving encryption key ck + * @param ik buffer receiving integrity key ik + * @param res buffer receiving authentication result res + * @param res_len nubmer of bytes written to res buffer + * @return SUCCESS, FAILED, or INVALID_STATE if out of sync + */ + status_t (*get_quintuplet)(sim_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], + char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], + char res[AKA_RES_MAX], int *res_len); + + /** + * Calculate AUTS from RAND for AKA resynchronization. + * + * @param id permanent identity to request quintuplet for + * @param rand random value rand + * @param auts resynchronization parameter auts + * @return TRUE if parameter generated successfully + */ + bool (*resync)(sim_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); + + /** + * Set the pseudonym to use for next authentication. + * + * @param id permanent identity of the peer + * @param pseudonym pseudonym identity received from the server + */ + void (*set_pseudonym)(sim_card_t *this, identification_t *id, + identification_t *pseudonym); + + /** + * Get the pseudonym previously stored via set_pseudonym(). + * + * @param id permanent identity of the peer + * @return associated pseudonym identity, NULL if none stored + */ + identification_t* (*get_pseudonym)(sim_card_t *this, identification_t *id); + + /** + * Store parameters to use for the next fast reauthentication. + * + * @param id permanent identity of the peer + * @param next next fast reauthentication identity to use + * @param mk master key MK to store for reauthentication + * @param counter counter value to store, host order + */ + void (*set_reauth)(sim_card_t *this, identification_t *id, + identification_t *next, char mk[HASH_SIZE_SHA1], + u_int16_t counter); + + /** + * Retrieve parameters for fast reauthentication stored via set_reauth(). + * + * @param id permanent identity of the peer + * @param mk buffer receiving master key MK + * @param counter pointer receiving counter value, in host order + * @return fast reauthentication identity, NULL if not found + */ + identification_t* (*get_reauth)(sim_card_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1], u_int16_t *counter); +}; + +#endif /** SIM_CARD_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_hooks.h b/src/libcharon/sa/authenticators/eap/sim_hooks.h new file mode 100644 index 000000000..0a675e4ab --- /dev/null +++ b/src/libcharon/sa/authenticators/eap/sim_hooks.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sim_hooks sim_hooks + * @{ @ingroup eap + */ + +#ifndef SIM_HOOKS_H_ +#define SIM_HOOKS_H_ + +typedef struct sim_hooks_t sim_hooks_t; + +/** + * Additional hooks invoked during EAP-SIM/AKA message processing. + */ +struct sim_hooks_t { + + /** + * SIM/AKA message parsing. + * + * As a SIM/AKA optionally contains encrypted attributes, the hook + * might get invoked twice, once before and once after decryption. + * + * @param message SIM/AKA message + * @param inbound TRUE for incoming messages, FALSE for outgoing + * @param decrypted TRUE if AT_ENCR_DATA has been decrypted + */ + void (*message)(sim_hooks_t *this, simaka_message_t *message, + bool inbound, bool decrypted); + + /** + * SIM/AKA encryption/authentication key hooks. + * + * @param k_encr derived SIM/AKA encryption key k_encr + * @param k_auth derived SIM/AKA authentication key k_auth + */ + void (*keys)(sim_hooks_t *this, chunk_t k_encr, chunk_t k_auth); +}; + +#endif /** SIM_HOOKS_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.c b/src/libcharon/sa/authenticators/eap/sim_manager.c index 157865083..9ccaf5298 100644 --- a/src/libcharon/sa/authenticators/eap/sim_manager.c +++ b/src/libcharon/sa/authenticators/eap/sim_manager.c @@ -17,6 +17,7 @@ #include <daemon.h> #include <utils/linked_list.h> +#include <threading/rwlock.h> typedef struct private_sim_manager_t private_sim_manager_t; @@ -44,65 +45,67 @@ struct private_sim_manager_t { * list of added hooks */ linked_list_t *hooks; + + /** + * lock for lists above + */ + rwlock_t *lock; }; -/** - * Implementation of sim_manager_t.add_card - */ -static void add_card(private_sim_manager_t *this, sim_card_t *card) +METHOD(sim_manager_t, add_card, void, + private_sim_manager_t *this, sim_card_t *card) { + this->lock->write_lock(this->lock); this->cards->insert_last(this->cards, card); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.remove_card - */ -static void remove_card(private_sim_manager_t *this, sim_card_t *card) +METHOD(sim_manager_t, remove_card, void, + private_sim_manager_t *this, sim_card_t *card) { + this->lock->write_lock(this->lock); this->cards->remove(this->cards, card, NULL); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.card_get_triplet - */ -static bool card_get_triplet(private_sim_manager_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]) +METHOD(sim_manager_t, card_get_triplet, bool, + private_sim_manager_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { enumerator_t *enumerator; sim_card_t *card; int tried = 0; + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { if (card->get_triplet(card, id, rand, sres, kc)) { enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return TRUE; } tried++; } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'", tried, id); return FALSE; } -/** - * Implementation of sim_manager_t.card_get_quintuplet - */ -static status_t card_get_quintuplet(private_sim_manager_t *this, - identification_t *id, char rand[AKA_RAND_LEN], - char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], - char ik[AKA_IK_LEN], char res[AKA_RES_MAX], - int *res_len) +METHOD(sim_manager_t, card_get_quintuplet, status_t, + private_sim_manager_t *this, identification_t *id, char rand[AKA_RAND_LEN], + char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], + char res[AKA_RES_MAX], int *res_len) { enumerator_t *enumerator; sim_card_t *card; status_t status = NOT_FOUND; int tried = 0; + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { @@ -112,6 +115,7 @@ static status_t card_get_quintuplet(private_sim_manager_t *this, case SUCCESS: case INVALID_STATE: enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return status; case NOT_SUPPORTED: case FAILED: @@ -121,62 +125,62 @@ static status_t card_get_quintuplet(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'", tried, id); return status; } -/** - * Implementation of sim_manager_t.card_resync - */ -static bool card_resync(private_sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) +METHOD(sim_manager_t, card_resync, bool, + private_sim_manager_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) { enumerator_t *enumerator; sim_card_t *card; + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { if (card->resync(card, id, rand, auts)) { enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return TRUE; } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return FALSE; } -/** - * Implementation of sim_manager_t.card_set_pseudonym - */ -static void card_set_pseudonym(private_sim_manager_t *this, - identification_t *id, identification_t *pseudonym) +METHOD(sim_manager_t, card_set_pseudonym, void, + private_sim_manager_t *this, identification_t *id, + identification_t *pseudonym) { enumerator_t *enumerator; sim_card_t *card; DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id); + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { card->set_pseudonym(card, id, pseudonym); } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.card_get_pseudonym - */ -static identification_t* card_get_pseudonym(private_sim_manager_t *this, - identification_t *id) +METHOD(sim_manager_t, card_get_pseudonym, identification_t*, + private_sim_manager_t *this, identification_t *id) { enumerator_t *enumerator; sim_card_t *card; identification_t *pseudonym = NULL; + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { @@ -189,15 +193,13 @@ static identification_t* card_get_pseudonym(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return pseudonym; } -/** - * Implementation of sim_manager_t.card_set_reauth - */ -static void card_set_reauth(private_sim_manager_t *this, identification_t *id, - identification_t *next, char mk[HASH_SIZE_SHA1], - u_int16_t counter) +METHOD(sim_manager_t, card_set_reauth, void, + private_sim_manager_t *this, identification_t *id, identification_t *next, + char mk[HASH_SIZE_SHA1], u_int16_t counter) { enumerator_t *enumerator; sim_card_t *card; @@ -205,25 +207,25 @@ static void card_set_reauth(private_sim_manager_t *this, identification_t *id, DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'", next, id); + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { card->set_reauth(card, id, next, mk, counter); } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.card_get_reauth - */ -static identification_t* card_get_reauth(private_sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) +METHOD(sim_manager_t, card_get_reauth, identification_t*, + private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1], + u_int16_t *counter) { enumerator_t *enumerator; sim_card_t *card; identification_t *reauth = NULL; + this->lock->read_lock(this->lock); enumerator = this->cards->create_enumerator(this->cards); while (enumerator->enumerate(enumerator, &card)) { @@ -236,66 +238,63 @@ static identification_t* card_get_reauth(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return reauth; } -/** - * Implementation of sim_manager_t.add_provider - */ -static void add_provider(private_sim_manager_t *this, sim_provider_t *provider) +METHOD(sim_manager_t, add_provider, void, + private_sim_manager_t *this, sim_provider_t *provider) { + this->lock->write_lock(this->lock); this->providers->insert_last(this->providers, provider); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.remove_provider - */ -static void remove_provider(private_sim_manager_t *this, - sim_provider_t *provider) +METHOD(sim_manager_t, remove_provider, void, + private_sim_manager_t *this, sim_provider_t *provider) { + this->lock->write_lock(this->lock); this->providers->remove(this->providers, provider, NULL); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.provider_get_triplet - */ -static bool provider_get_triplet(private_sim_manager_t *this, - identification_t *id, char rand[SIM_RAND_LEN], - char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) +METHOD(sim_manager_t, provider_get_triplet, bool, + private_sim_manager_t *this, identification_t *id, char rand[SIM_RAND_LEN], + char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { enumerator_t *enumerator; sim_provider_t *provider; int tried = 0; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { if (provider->get_triplet(provider, id, rand, sres, kc)) { enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return TRUE; } tried++; } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", tried, id); return FALSE; } -/** - * Implementation of sim_manager_t.provider_get_quintuplet - */ -static bool provider_get_quintuplet(private_sim_manager_t *this, - identification_t *id, char rand[AKA_RAND_LEN], - char xres[AKA_RES_MAX], int *xres_len, - char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], - char autn[AKA_AUTN_LEN]) +METHOD(sim_manager_t, provider_get_quintuplet, bool, + private_sim_manager_t *this, identification_t *id, char rand[AKA_RAND_LEN], + char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]) { enumerator_t *enumerator; sim_provider_t *provider; int tried = 0; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { @@ -303,47 +302,48 @@ static bool provider_get_quintuplet(private_sim_manager_t *this, ck, ik, autn)) { enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return TRUE; } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'", tried, id); return FALSE; } -/** - * Implementation of sim_manager_t.provider_resync - */ -static bool provider_resync(private_sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) +METHOD(sim_manager_t, provider_resync, bool, + private_sim_manager_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) { enumerator_t *enumerator; sim_provider_t *provider; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { if (provider->resync(provider, id, rand, auts)) { enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return TRUE; } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return FALSE; } -/** - * Implementation of sim_manager_t.provider_is_pseudonym - */ -static identification_t* provider_is_pseudonym(private_sim_manager_t *this, - identification_t *id) +METHOD(sim_manager_t, provider_is_pseudonym, identification_t*, + private_sim_manager_t *this, identification_t *id) { enumerator_t *enumerator; sim_provider_t *provider; identification_t *permanent = NULL; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { @@ -356,19 +356,18 @@ static identification_t* provider_is_pseudonym(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return permanent; } -/** - * Implementation of sim_manager_t.provider_gen_pseudonym - */ -static identification_t* provider_gen_pseudonym(private_sim_manager_t *this, - identification_t *id) +METHOD(sim_manager_t, provider_gen_pseudonym, identification_t*, + private_sim_manager_t *this, identification_t *id) { enumerator_t *enumerator; sim_provider_t *provider; identification_t *pseudonym = NULL; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { @@ -380,20 +379,19 @@ static identification_t* provider_gen_pseudonym(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return pseudonym; } -/** - * Implementation of sim_manager_t.provider_is_reauth - */ -static identification_t* provider_is_reauth(private_sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) +METHOD(sim_manager_t, provider_is_reauth, identification_t*, + private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1], + u_int16_t *counter) { enumerator_t *enumerator; sim_provider_t *provider; identification_t *permanent = NULL; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { @@ -406,19 +404,18 @@ static identification_t* provider_is_reauth(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return permanent; } -/** - * Implementation of sim_manager_t.provider_gen_reauth - */ -static identification_t* provider_gen_reauth(private_sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1]) +METHOD(sim_manager_t, provider_gen_reauth, identification_t*, + private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1]) { enumerator_t *enumerator; sim_provider_t *provider; identification_t *reauth = NULL; + this->lock->read_lock(this->lock); enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, &provider)) { @@ -430,67 +427,66 @@ static identification_t* provider_gen_reauth(private_sim_manager_t *this, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); return reauth; } -/** - * Implementation of sim_manager_t.add_hooks - */ -static void add_hooks(private_sim_manager_t *this, sim_hooks_t *hooks) +METHOD(sim_manager_t, add_hooks, void, + private_sim_manager_t *this, sim_hooks_t *hooks) { + this->lock->write_lock(this->lock); this->hooks->insert_last(this->hooks, hooks); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.remove_hooks - */ -static void remove_hooks(private_sim_manager_t *this, sim_hooks_t *hooks) +METHOD(sim_manager_t, remove_hooks, void, + private_sim_manager_t *this, sim_hooks_t *hooks) { + this->lock->write_lock(this->lock); this->hooks->remove(this->hooks, hooks, NULL); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.message_hook - */ -static void message_hook(private_sim_manager_t *this, - simaka_message_t *message, bool inbound, bool decrypted) +METHOD(sim_manager_t, message_hook, void, + private_sim_manager_t *this, simaka_message_t *message, + bool inbound, bool decrypted) { enumerator_t *enumerator; sim_hooks_t *hooks; + this->lock->read_lock(this->lock); enumerator = this->hooks->create_enumerator(this->hooks); while (enumerator->enumerate(enumerator, &hooks)) { hooks->message(hooks, message, inbound, decrypted); } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.key_hook - */ -static void key_hook(private_sim_manager_t *this, - chunk_t k_encr, chunk_t k_auth) +METHOD(sim_manager_t, key_hook, void, + private_sim_manager_t *this, chunk_t k_encr, chunk_t k_auth) { enumerator_t *enumerator; sim_hooks_t *hooks; + this->lock->read_lock(this->lock); enumerator = this->hooks->create_enumerator(this->hooks); while (enumerator->enumerate(enumerator, &hooks)) { hooks->keys(hooks, k_encr, k_auth); } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } -/** - * Implementation of sim_manager_t.destroy. - */ -static void destroy(private_sim_manager_t *this) +METHOD(sim_manager_t, destroy, void, + private_sim_manager_t *this) { this->cards->destroy(this->cards); this->providers->destroy(this->providers); this->hooks->destroy(this->hooks); + this->lock->destroy(this->lock); free(this); } @@ -499,35 +495,39 @@ static void destroy(private_sim_manager_t *this) */ sim_manager_t *sim_manager_create() { - private_sim_manager_t *this = malloc_thing(private_sim_manager_t); - - this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card; - this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card; - this->public.card_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))card_get_triplet; - this->public.card_get_quintuplet = (status_t(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))card_get_quintuplet; - this->public.card_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))card_resync; - this->public.card_set_pseudonym = (void(*)(sim_manager_t*, identification_t *id, identification_t *pseudonym))card_set_pseudonym; - this->public.card_get_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))card_get_pseudonym; - this->public.card_set_reauth = (void(*)(sim_manager_t*, identification_t *id, identification_t *next, char mk[HASH_SIZE_SHA1], u_int16_t counter))card_set_reauth; - this->public.card_get_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))card_get_reauth; - this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider; - this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider; - this->public.provider_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))provider_get_triplet; - this->public.provider_get_quintuplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))provider_get_quintuplet; - this->public.provider_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))provider_resync; - this->public.provider_is_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_is_pseudonym; - this->public.provider_gen_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_gen_pseudonym; - this->public.provider_is_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))provider_is_reauth; - this->public.provider_gen_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))provider_gen_reauth; - this->public.add_hooks = (void(*)(sim_manager_t*, sim_hooks_t *hooks))add_hooks; - this->public.remove_hooks = (void(*)(sim_manager_t*, sim_hooks_t *hooks))remove_hooks; - this->public.message_hook = (void(*)(sim_manager_t*, simaka_message_t *message, bool inbound, bool decrypted))message_hook; - this->public.key_hook = (void(*)(sim_manager_t*, chunk_t k_encr, chunk_t k_auth))key_hook; - this->public.destroy = (void(*)(sim_manager_t*))destroy; - - this->cards = linked_list_create(); - this->providers = linked_list_create(); - this->hooks = linked_list_create(); + private_sim_manager_t *this; + + INIT(this, + .public = { + .add_card = _add_card, + .remove_card = _remove_card, + .card_get_triplet = _card_get_triplet, + .card_get_quintuplet = _card_get_quintuplet, + .card_resync = _card_resync, + .card_set_pseudonym = _card_set_pseudonym, + .card_get_pseudonym = _card_get_pseudonym, + .card_set_reauth = _card_set_reauth, + .card_get_reauth = _card_get_reauth, + .add_provider = _add_provider, + .remove_provider = _remove_provider, + .provider_get_triplet = _provider_get_triplet, + .provider_get_quintuplet = _provider_get_quintuplet, + .provider_resync = _provider_resync, + .provider_is_pseudonym = _provider_is_pseudonym, + .provider_gen_pseudonym = _provider_gen_pseudonym, + .provider_is_reauth = _provider_is_reauth, + .provider_gen_reauth = _provider_gen_reauth, + .add_hooks = _add_hooks, + .remove_hooks = _remove_hooks, + .message_hook = _message_hook, + .key_hook = _key_hook, + .destroy = _destroy, + }, + .cards = linked_list_create(), + .providers = linked_list_create(), + .hooks = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); return &this->public; } diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.h b/src/libcharon/sa/authenticators/eap/sim_manager.h index 9aa661ac8..db4a65011 100644 --- a/src/libcharon/sa/authenticators/eap/sim_manager.h +++ b/src/libcharon/sa/authenticators/eap/sim_manager.h @@ -27,9 +27,6 @@ #include <sa/authenticators/eap/eap_method.h> typedef struct sim_manager_t sim_manager_t; -typedef struct sim_card_t sim_card_t; -typedef struct sim_provider_t sim_provider_t; -typedef struct sim_hooks_t sim_hooks_t; /** implemented in libsimaka, but we need it for the message hook */ typedef struct simaka_message_t simaka_message_t; @@ -45,229 +42,9 @@ typedef struct simaka_message_t simaka_message_t; #define AKA_AUTN_LEN 16 #define AKA_AUTS_LEN 14 -/** - * Interface for a (U)SIM card (used as EAP client). - * - * The SIM card completes triplets/quintuplets requested in a challenge - * received from the server. - * An implementation supporting only one of SIM/AKA authentication may - * implement the other methods with return_false()/return NOT_SUPPORTED/NULL. - */ -struct sim_card_t { - - /** - * Calculate SRES/KC from a RAND for SIM authentication. - * - * @param id permanent identity to get a triplet for - * @param rand RAND input buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if SRES/KC calculated, FALSE on error/wrong identity - */ - bool (*get_triplet)(sim_card_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Calculate CK/IK/RES from RAND/AUTN for AKA authentication. - * - * If the received sequence number (in autn) is out of sync, INVALID_STATE - * is returned. - * The RES value is the only one with variable length. Pass a buffer - * of at least AKA_RES_MAX, the actual number of bytes is written to the - * res_len value. While the standard would allow any bit length between - * 32 and 128 bits, we support only full bytes for now. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param autn authentication token autn - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param res buffer receiving authentication result res - * @param res_len nubmer of bytes written to res buffer - * @return SUCCESS, FAILED, or INVALID_STATE if out of sync - */ - status_t (*get_quintuplet)(sim_card_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], - char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], - char res[AKA_RES_MAX], int *res_len); - - /** - * Calculate AUTS from RAND for AKA resynchronization. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param auts resynchronization parameter auts - * @return TRUE if parameter generated successfully - */ - bool (*resync)(sim_card_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Set the pseudonym to use for next authentication. - * - * @param id permanent identity of the peer - * @param pseudonym pseudonym identity received from the server - */ - void (*set_pseudonym)(sim_card_t *this, identification_t *id, - identification_t *pseudonym); - - /** - * Get the pseudonym previously stored via set_pseudonym(). - * - * @param id permanent identity of the peer - * @return associated pseudonym identity, NULL if none stored - */ - identification_t* (*get_pseudonym)(sim_card_t *this, identification_t *id); - - /** - * Store parameters to use for the next fast reauthentication. - * - * @param id permanent identity of the peer - * @param next next fast reauthentication identity to use - * @param mk master key MK to store for reauthentication - * @param counter counter value to store, host order - */ - void (*set_reauth)(sim_card_t *this, identification_t *id, - identification_t *next, char mk[HASH_SIZE_SHA1], - u_int16_t counter); - - /** - * Retrieve parameters for fast reauthentication stored via set_reauth(). - * - * @param id permanent identity of the peer - * @param mk buffer receiving master key MK - * @param counter pointer receiving counter value, in host order - * @return fast reauthentication identity, NULL if not found - */ - identification_t* (*get_reauth)(sim_card_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1], u_int16_t *counter); -}; - -/** - * Interface for a triplet/quintuplet provider (used as EAP server). - * - * A SIM provider hands out triplets for SIM authentication and quintuplets - * for AKA authentication. Multiple SIM provider instances can serve as - * authentication backend to authenticate clients using SIM/AKA. - * An implementation supporting only one of SIM/AKA authentication may - * implement the other methods with return_false(). - */ -struct sim_provider_t { - - /** - * Create a challenge for SIM authentication. - * - * @param id permanent identity of peer to gen triplet for - * @param rand RAND output buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if triplet received, FALSE otherwise - */ - bool (*get_triplet)(sim_provider_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Create a challenge for AKA authentication. - * - * The XRES value is the only one with variable length. Pass a buffer - * of at least AKA_RES_MAX, the actual number of bytes is written to the - * xres_len value. While the standard would allow any bit length between - * 32 and 128 bits, we support only full bytes for now. - * - * @param id permanent identity of peer to create challenge for - * @param rand buffer receiving random value rand - * @param xres buffer receiving expected authentication result xres - * @param xres_len nubmer of bytes written to xres buffer - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param autn authentication token autn - * @return TRUE if quintuplet generated successfully - */ - bool (*get_quintuplet)(sim_provider_t *this, identification_t *id, - char rand[AKA_RAND_LEN], - char xres[AKA_RES_MAX], int *xres_len, - char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], - char autn[AKA_AUTN_LEN]); - - /** - * Process AKA resynchroniusation request of a peer. - * - * @param id permanent identity of peer requesting resynchronisation - * @param rand random value rand - * @param auts synchronization parameter auts - * @return TRUE if resynchronized successfully - */ - bool (*resync)(sim_provider_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Check if peer uses a pseudonym, get permanent identity. - * - * @param id pseudonym identity candidate - * @return permanent identity, NULL if id not a pseudonym - */ - identification_t* (*is_pseudonym)(sim_provider_t *this, - identification_t *id); - - /** - * Generate a pseudonym identitiy for a given peer identity. - * - * @param id permanent identity to generate a pseudonym for - * @return generated pseudonym, NULL to not use a pseudonym identity - */ - identification_t* (*gen_pseudonym)(sim_provider_t *this, - identification_t *id); - - /** - * Check if peer uses reauthentication, retrieve reauth parameters. - * - * @param id reauthentication identity (candidate) - * @param mk buffer receiving master key MK - * @param counter pointer receiving current counter value, host order - * @return permanent identity, NULL if id not a reauth identity - */ - identification_t* (*is_reauth)(sim_provider_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1], u_int16_t *counter); - - /** - * Generate a fast reauthentication identity, associated to a master key. - * - * @param id permanent peer identity - * @param mk master key to store along with generated identity - * @return fast reauthentication identity, NULL to not use reauth - */ - identification_t* (*gen_reauth)(sim_provider_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1]); -}; - -/** - * Additional hooks invoked during EAP-SIM/AKA message processing. - */ -struct sim_hooks_t { - - /** - * SIM/AKA message parsing. - * - * As a SIM/AKA optionally contains encrypted attributes, the hook - * might get invoked twice, once before and once after decryption. - * - * @param message SIM/AKA message - * @param inbound TRUE for incoming messages, FALSE for outgoing - * @param decrypted TRUE if AT_ENCR_DATA has been decrypted - */ - void (*message)(sim_hooks_t *this, simaka_message_t *message, - bool inbound, bool decrypted); - - /** - * SIM/AKA encryption/authentication key hooks. - * - * @param k_encr derived SIM/AKA encryption key k_encr - * @param k_auth derived SIM/AKA authentication key k_auth - */ - void (*keys)(sim_hooks_t *this, chunk_t k_encr, chunk_t k_auth); -}; +#include <sa/authenticators/eap/sim_card.h> +#include <sa/authenticators/eap/sim_provider.h> +#include <sa/authenticators/eap/sim_hooks.h> /** * The SIM manager handles multiple (U)SIM cards/providers and hooks. diff --git a/src/libcharon/sa/authenticators/eap/sim_provider.h b/src/libcharon/sa/authenticators/eap/sim_provider.h new file mode 100644 index 000000000..191e094db --- /dev/null +++ b/src/libcharon/sa/authenticators/eap/sim_provider.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2008-2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sim_provider sim_provider + * @{ @ingroup eap + */ + +#ifndef SIM_PROVIDER_H_ +#define SIM_PROVIDER_H_ + +typedef struct sim_provider_t sim_provider_t; + +/** + * Interface for a triplet/quintuplet provider (used as EAP server). + * + * A SIM provider hands out triplets for SIM authentication and quintuplets + * for AKA authentication. Multiple SIM provider instances can serve as + * authentication backend to authenticate clients using SIM/AKA. + * An implementation supporting only one of SIM/AKA authentication may + * implement the other methods with return_false(). + */ +struct sim_provider_t { + + /** + * Create a challenge for SIM authentication. + * + * @param id permanent identity of peer to gen triplet for + * @param rand RAND output buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if triplet received, FALSE otherwise + */ + bool (*get_triplet)(sim_provider_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], + char kc[SIM_KC_LEN]); + + /** + * Create a challenge for AKA authentication. + * + * The XRES value is the only one with variable length. Pass a buffer + * of at least AKA_RES_MAX, the actual number of bytes is written to the + * xres_len value. While the standard would allow any bit length between + * 32 and 128 bits, we support only full bytes for now. + * + * @param id permanent identity of peer to create challenge for + * @param rand buffer receiving random value rand + * @param xres buffer receiving expected authentication result xres + * @param xres_len nubmer of bytes written to xres buffer + * @param ck buffer receiving encryption key ck + * @param ik buffer receiving integrity key ik + * @param autn authentication token autn + * @return TRUE if quintuplet generated successfully + */ + bool (*get_quintuplet)(sim_provider_t *this, identification_t *id, + char rand[AKA_RAND_LEN], + char xres[AKA_RES_MAX], int *xres_len, + char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], + char autn[AKA_AUTN_LEN]); + + /** + * Process AKA resynchroniusation request of a peer. + * + * @param id permanent identity of peer requesting resynchronisation + * @param rand random value rand + * @param auts synchronization parameter auts + * @return TRUE if resynchronized successfully + */ + bool (*resync)(sim_provider_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); + + /** + * Check if peer uses a pseudonym, get permanent identity. + * + * @param id pseudonym identity candidate + * @return permanent identity, NULL if id not a pseudonym + */ + identification_t* (*is_pseudonym)(sim_provider_t *this, + identification_t *id); + + /** + * Generate a pseudonym identitiy for a given peer identity. + * + * @param id permanent identity to generate a pseudonym for + * @return generated pseudonym, NULL to not use a pseudonym identity + */ + identification_t* (*gen_pseudonym)(sim_provider_t *this, + identification_t *id); + + /** + * Check if peer uses reauthentication, retrieve reauth parameters. + * + * @param id reauthentication identity (candidate) + * @param mk buffer receiving master key MK + * @param counter pointer receiving current counter value, host order + * @return permanent identity, NULL if id not a reauth identity + */ + identification_t* (*is_reauth)(sim_provider_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1], u_int16_t *counter); + + /** + * Generate a fast reauthentication identity, associated to a master key. + * + * @param id permanent peer identity + * @param mk master key to store along with generated identity + * @return fast reauthentication identity, NULL to not use reauth + */ + identification_t* (*gen_reauth)(sim_provider_t *this, identification_t *id, + char mk[HASH_SIZE_SHA1]); +}; + +#endif /** SIM_CARD_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c index dea02755d..d442acb00 100644 --- a/src/libcharon/sa/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/authenticators/eap_authenticator.c @@ -183,16 +183,18 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, if (this->method) { action = "initiating"; + type = this->method->get_type(this->method, &vendor); if (this->method->initiate(this->method, &out) == NEED_MORE) { if (vendor) { - DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method", - type, vendor); + DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method (id 0x%02X)", + type, vendor, out->get_identifier(out)); } else { - DBG1(DBG_IKE, "initiating %N method", eap_type_names, type); + DBG1(DBG_IKE, "initiating %N method (id 0x%02X)", eap_type_names, + type, out->get_identifier(out)); } return out; } @@ -371,13 +373,13 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, { if (vendor) { - DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d", - type, vendor); + DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d ", + "(id 0x%02X)", type, vendor, in->get_identifier(in)); } else { - DBG1(DBG_IKE, "server requested %N authentication", - eap_type_names, type); + DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)", + eap_type_names, type, in->get_identifier(in)); } this->method = load_method(this, type, vendor, EAP_PEER); if (!this->method) diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index 495929965..dc42ba787 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -563,6 +563,7 @@ METHOD(child_sa_t, install, status_t, linked_list_t *other_ts) { u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size; + u_int16_t esn = NO_EXT_SEQ_NUMBERS; traffic_selector_t *src_ts = NULL, *dst_ts = NULL; time_t now; lifetime_cfg_t *lifetime; @@ -608,6 +609,8 @@ METHOD(child_sa_t, install, status_t, &enc_alg, &size); this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM, &int_alg, &size); + this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS, + &esn, NULL); lifetime = this->config->get_lifetime(this->config); @@ -647,7 +650,7 @@ METHOD(child_sa_t, install, status_t, src, dst, spi, proto_ike2ip(this->protocol), this->reqid, inbound ? this->mark_in : this->mark_out, tfc, lifetime, enc_alg, encr, int_alg, integ, this->mode, - this->ipcomp, cpi, this->encap, update, src_ts, dst_ts); + this->ipcomp, cpi, this->encap, esn, update, src_ts, dst_ts); free(lifetime); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 9b6f9d06d..2fc186fe8 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -1573,7 +1573,7 @@ METHOD(ike_sa_t, reestablish, status_t, #endif /* ME */ )) { - DBG1(DBG_IKE, "unable to reestablish IKE_SA due asymetric setup"); + DBG1(DBG_IKE, "unable to reestablish IKE_SA due to asymmetric setup"); return FAILED; } @@ -1896,7 +1896,7 @@ METHOD(ike_sa_t, create_task_enumerator, enumerator_t*, return this->task_manager->create_task_enumerator(this->task_manager, queue); } -METHOD(ike_sa_t, inherit, status_t, +METHOD(ike_sa_t, inherit, void, private_ike_sa_t *this, ike_sa_t *other_public) { private_ike_sa_t *other = (private_ike_sa_t*)other_public; @@ -1977,8 +1977,6 @@ METHOD(ike_sa_t, inherit, status_t, lib->scheduler->schedule_job(lib->scheduler, (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE), delete); } - /* we have to initate here, there may be new tasks to handle */ - return this->task_manager->initiate(this->task_manager); } METHOD(ike_sa_t, destroy, void, @@ -1989,6 +1987,7 @@ METHOD(ike_sa_t, destroy, void, charon->bus->set_sa(charon->bus, &this->public); set_state(this, IKE_DESTROYING); + this->task_manager->destroy(this->task_manager); /* remove attributes first, as we pass the IKE_SA to the handler */ while (this->attributes->remove_last(this->attributes, @@ -2006,7 +2005,6 @@ METHOD(ike_sa_t, destroy, void, /* unset SA after here to avoid usage by the listeners */ charon->bus->set_sa(charon->bus, NULL); - this->task_manager->destroy(this->task_manager); this->keymat->destroy(this->keymat); if (this->my_virtual_ip) diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index 988100bcc..69a74d8b7 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -912,9 +912,8 @@ struct ike_sa_t { * As this call may initiate inherited tasks, a status is returned. * * @param other other task to inherit from - * @return DESTROY_ME if initiation of inherited task failed */ - status_t (*inherit) (ike_sa_t *this, ike_sa_t *other); + void (*inherit) (ike_sa_t *this, ike_sa_t *other); /** * Reset the IKE_SA, useable when initiating fails diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c index 9467d1586..f07d2e384 100644 --- a/src/libcharon/sa/task_manager.c +++ b/src/libcharon/sa/task_manager.c @@ -161,12 +161,12 @@ static void flush(private_task_manager_t *this) { this->queued_tasks->destroy_offset(this->queued_tasks, offsetof(task_t, destroy)); + this->queued_tasks = linked_list_create(); this->passive_tasks->destroy_offset(this->passive_tasks, offsetof(task_t, destroy)); + this->passive_tasks = linked_list_create(); this->active_tasks->destroy_offset(this->active_tasks, offsetof(task_t, destroy)); - this->queued_tasks = linked_list_create(); - this->passive_tasks = linked_list_create(); this->active_tasks = linked_list_create(); } @@ -545,7 +545,7 @@ static status_t process_response(private_task_manager_t *this, /** * handle exchange collisions */ -static void handle_collisions(private_task_manager_t *this, task_t *task) +static bool handle_collisions(private_task_manager_t *this, task_t *task) { iterator_t *iterator; task_t *active; @@ -584,12 +584,11 @@ static void handle_collisions(private_task_manager_t *this, task_t *task) continue; } iterator->destroy(iterator); - return; + return TRUE; } iterator->destroy(iterator); } - /* destroy task if not registered in any active task */ - task->destroy(task); + return FALSE; } /** @@ -623,9 +622,17 @@ static status_t build_response(private_task_manager_t *this, message_t *request) case SUCCESS: /* task completed, remove it */ iterator->remove(iterator); - handle_collisions(this, task); + if (!handle_collisions(this, task)) + { + task->destroy(task); + } + break; case NEED_MORE: /* processed, but task needs another exchange */ + if (handle_collisions(this, task)) + { + iterator->remove(iterator); + } break; case FAILED: default: diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c index 45e97e4cd..e6834a93c 100644 --- a/src/libcharon/sa/tasks/child_delete.c +++ b/src/libcharon/sa/tasks/child_delete.c @@ -163,6 +163,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message) protocol, spi); continue; } + /* fall through */ case CHILD_INSTALLED: if (!this->initiator) { /* reestablish installed children if required */ diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c index e74ca4eef..b39a5fc67 100644 --- a/src/libcharon/sa/tasks/child_rekey.c +++ b/src/libcharon/sa/tasks/child_rekey.c @@ -382,7 +382,7 @@ static void collide(private_child_rekey_t *this, task_t *other) if (other->get_type(other) == CHILD_REKEY) { private_child_rekey_t *rekey = (private_child_rekey_t*)other; - if (rekey == NULL || rekey->child_sa != this->child_sa) + if (rekey->child_sa != this->child_sa) { /* not the same child => no collision */ other->destroy(other); @@ -399,7 +399,7 @@ static void collide(private_child_rekey_t *this, task_t *other) other->destroy(other); return; } - if (del == NULL || del->get_child(del) != this->child_sa) + if (del->get_child(del) != this->child_sa) { /* not the same child => no collision */ other->destroy(other); @@ -412,6 +412,8 @@ static void collide(private_child_rekey_t *this, task_t *other) other->destroy(other); return; } + DBG1(DBG_IKE, "detected %N collision with %N", task_type_names, CHILD_REKEY, + task_type_names, other->get_type(other)); DESTROY_IF(this->collision); this->collision = other; } diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c index c92b5bca5..a61663c48 100644 --- a/src/libcharon/sa/tasks/ike_config.c +++ b/src/libcharon/sa/tasks/ike_config.c @@ -317,7 +317,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message) id = this->ike_sa->get_other_eap_id(this->ike_sa); config = this->ike_sa->get_peer_cfg(this->ike_sa); - if (config && this->virtual_ip) + if (this->virtual_ip) { DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip); if (config->get_pool(config)) diff --git a/src/libcharon/sa/tasks/ike_rekey.c b/src/libcharon/sa/tasks/ike_rekey.c index 44c55036e..c055dabc1 100644 --- a/src/libcharon/sa/tasks/ike_rekey.c +++ b/src/libcharon/sa/tasks/ike_rekey.c @@ -68,9 +68,45 @@ struct private_ike_rekey_t { }; /** - * Implementation of task_t.build for initiator, after rekeying + * Establish the new replacement IKE_SA */ -static status_t build_i_delete(private_ike_rekey_t *this, message_t *message) +static void establish_new(private_ike_rekey_t *this) +{ + if (this->new_sa) + { + this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); + DBG0(DBG_IKE, "IKE_SA %s[%d] rekeyed between %H[%Y]...%H[%Y]", + this->new_sa->get_name(this->new_sa), + this->new_sa->get_unique_id(this->new_sa), + this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa)); + + this->new_sa->inherit(this->new_sa, this->ike_sa); + charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa); + this->new_sa = NULL; + /* set threads active IKE_SA after checkin */ + charon->bus->set_sa(charon->bus, this->ike_sa); + } +} + +METHOD(task_t, process_r_delete, status_t, + private_ike_rekey_t *this, message_t *message) +{ + establish_new(this); + return this->ike_delete->task.process(&this->ike_delete->task, message); +} + +METHOD(task_t, build_r_delete, status_t, + private_ike_rekey_t *this, message_t *message) +{ + return this->ike_delete->task.build(&this->ike_delete->task, message); +} + +METHOD(task_t, build_i_delete, status_t, + private_ike_rekey_t *this, message_t *message) { /* update exchange type to INFORMATIONAL for the delete */ message->set_exchange_type(message, INFORMATIONAL); @@ -78,18 +114,14 @@ static status_t build_i_delete(private_ike_rekey_t *this, message_t *message) return this->ike_delete->task.build(&this->ike_delete->task, message); } -/** - * Implementation of task_t.process for initiator, after rekeying - */ -static status_t process_i_delete(private_ike_rekey_t *this, message_t *message) +METHOD(task_t, process_i_delete, status_t, + private_ike_rekey_t *this, message_t *message) { return this->ike_delete->task.process(&this->ike_delete->task, message); } -/** - * Implementation of task_t.build for initiator - */ -static status_t build_i(private_ike_rekey_t *this, message_t *message) +METHOD(task_t, build_i, status_t, + private_ike_rekey_t *this, message_t *message) { peer_cfg_t *peer_cfg; host_t *other_host; @@ -112,10 +144,8 @@ static status_t build_i(private_ike_rekey_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.process for responder - */ -static status_t process_r(private_ike_rekey_t *this, message_t *message) +METHOD(task_t, process_r, status_t, + private_ike_rekey_t *this, message_t *message) { peer_cfg_t *peer_cfg; iterator_t *iterator; @@ -156,10 +186,8 @@ static status_t process_r(private_ike_rekey_t *this, message_t *message) return NEED_MORE; } -/** - * Implementation of task_t.build for responder - */ -static status_t build_r(private_ike_rekey_t *this, message_t *message) +METHOD(task_t, build_r, status_t, + private_ike_rekey_t *this, message_t *message) { if (this->new_sa == NULL) { @@ -174,22 +202,17 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message) } this->ike_sa->set_state(this->ike_sa, IKE_REKEYING); - this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); - DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", - this->new_sa->get_name(this->new_sa), - this->new_sa->get_unique_id(this->new_sa), - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); - - return SUCCESS; + + /* rekeying successful, delete the IKE_SA using a subtask */ + this->ike_delete = ike_delete_create(this->ike_sa, FALSE); + this->public.task.build = _build_r_delete; + this->public.task.process = _process_r_delete; + + return NEED_MORE; } -/** - * Implementation of task_t.process for initiator - */ -static status_t process_i(private_ike_rekey_t *this, message_t *message) +METHOD(task_t, process_i, status_t, + private_ike_rekey_t *this, message_t *message) { if (message->get_notify(message, NO_ADDITIONAL_SAS)) { @@ -228,15 +251,6 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) break; } - this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); - DBG0(DBG_IKE, "IKE_SA %s[%d] established between %H[%Y]...%H[%Y]", - this->new_sa->get_name(this->new_sa), - this->new_sa->get_unique_id(this->new_sa), - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa)); - /* check for collisions */ if (this->collision && this->collision->get_type(this->collision) == IKE_REKEY) @@ -275,21 +289,20 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) host = this->ike_sa->get_other_host(this->ike_sa); this->new_sa->set_other_host(this->new_sa, host->clone(host)); this->ike_sa->set_state(this->ike_sa, IKE_ESTABLISHED); + this->new_sa->set_state(this->new_sa, IKE_REKEYING); if (this->new_sa->delete(this->new_sa) == DESTROY_ME) { - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, this->new_sa); + this->new_sa->destroy(this->new_sa); } else { charon->ike_sa_manager->checkin( charon->ike_sa_manager, this->new_sa); + /* set threads active IKE_SA after checkin */ + charon->bus->set_sa(charon->bus, this->ike_sa); } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - /* inherit to other->new_sa in destroy() */ - this->new_sa = other->new_sa; - other->new_sa = NULL; + this->new_sa = NULL; + establish_new(other); return SUCCESS; } } @@ -297,32 +310,33 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) charon->bus->set_sa(charon->bus, this->ike_sa); } + establish_new(this); + /* rekeying successful, delete the IKE_SA using a subtask */ this->ike_delete = ike_delete_create(this->ike_sa, TRUE); - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; + this->public.task.build = _build_i_delete; + this->public.task.process = _process_i_delete; return NEED_MORE; } -/** - * Implementation of task_t.get_type - */ -static task_type_t get_type(private_ike_rekey_t *this) +METHOD(task_t, get_type, task_type_t, + private_ike_rekey_t *this) { return IKE_REKEY; } -static void collide(private_ike_rekey_t* this, task_t *other) +METHOD(ike_rekey_t, collide, void, + private_ike_rekey_t* this, task_t *other) { + DBG1(DBG_IKE, "detected %N collision with %N", task_type_names, IKE_REKEY, + task_type_names, other->get_type(other)); DESTROY_IF(this->collision); this->collision = other; } -/** - * Implementation of task_t.migrate - */ -static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) +METHOD(task_t, migrate, void, + private_ike_rekey_t *this, ike_sa_t *ike_sa) { if (this->ike_init) { @@ -332,13 +346,7 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) { this->ike_delete->task.destroy(&this->ike_delete->task); } - if (this->new_sa) - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - this->new_sa); - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - } + DESTROY_IF(this->new_sa); DESTROY_IF(this->collision); this->collision = NULL; @@ -348,28 +356,9 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) this->ike_delete = NULL; } -/** - * Implementation of task_t.destroy - */ -static void destroy(private_ike_rekey_t *this) +METHOD(task_t, destroy, void, + private_ike_rekey_t *this) { - if (this->new_sa) - { - if (this->new_sa->get_state(this->new_sa) == IKE_ESTABLISHED && - this->new_sa->inherit(this->new_sa, this->ike_sa) != DESTROY_ME) - { - /* invoke hook if rekeying was successful */ - charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa); - charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa); - } - else - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - this->new_sa); - } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - } if (this->ike_init) { this->ike_init->task.destroy(&this->ike_init->task); @@ -378,6 +367,7 @@ static void destroy(private_ike_rekey_t *this) { this->ike_delete->task.destroy(&this->ike_delete->task); } + DESTROY_IF(this->new_sa); DESTROY_IF(this->collision); free(this); } @@ -387,29 +377,27 @@ static void destroy(private_ike_rekey_t *this) */ ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator) { - private_ike_rekey_t *this = malloc_thing(private_ike_rekey_t); - - this->public.collide = (void(*)(ike_rekey_t*,task_t*))collide; - this->public.task.get_type = (task_type_t(*)(task_t*))get_type; - this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; - this->public.task.destroy = (void(*)(task_t*))destroy; + private_ike_rekey_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .build = _build_r, + .process = _process_r, + .migrate = _migrate, + .destroy = _destroy, + }, + .collide = _collide, + }, + .ike_sa = ike_sa, + .initiator = initiator, + ); if (initiator) { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; + this->public.task.build = _build_i; + this->public.task.process = _process_i; } - else - { - this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; - this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; - } - - this->ike_sa = ike_sa; - this->new_sa = NULL; - this->ike_init = NULL; - this->ike_delete = NULL; - this->initiator = initiator; - this->collision = NULL; return &this->public; } diff --git a/src/libcharon/tnc/imc/imc_manager.h b/src/libcharon/tnc/imc/imc_manager.h index 634afdbe8..ad83cf552 100644 --- a/src/libcharon/tnc/imc/imc_manager.h +++ b/src/libcharon/tnc/imc/imc_manager.h @@ -49,6 +49,14 @@ struct imc_manager_t { imc_t* (*remove)(imc_manager_t *this, TNC_IMCID id); /** + * Check if an IMC with a given ID is registered with the IMC manager + * + * @param id ID of IMC instance + * @return TRUE if registered + */ + bool (*is_registered)(imc_manager_t *this, TNC_IMCID id); + + /** * Return the preferred language for recommendations * * @return preferred language string diff --git a/src/libcharon/tnc/imv/imv_manager.h b/src/libcharon/tnc/imv/imv_manager.h index b5c581a75..0dd2d6253 100644 --- a/src/libcharon/tnc/imv/imv_manager.h +++ b/src/libcharon/tnc/imv/imv_manager.h @@ -50,6 +50,15 @@ struct imv_manager_t { imv_t* (*remove)(imv_manager_t *this, TNC_IMVID id); /** + * Check if an IMV with a given ID is registered with the IMV manager + * + * @param id ID of IMV instance + * @return TRUE if registered + */ + bool (*is_registered)(imv_manager_t *this, TNC_IMVID id); + + + /** * Get the configured recommendation policy * * @return configured recommendation policy @@ -67,11 +76,13 @@ struct imv_manager_t { * Enforce the TNC recommendation on the IKE_SA by either inserting an * allow|isolate group membership rule (TRUE) or by blocking access (FALSE) * - * @param void TNC action recommendation + * @param rec TNC action recommendation + * @param eval TNC evaluation result * @return TRUE for allow|isolate, FALSE for none */ bool (*enforce_recommendation)(imv_manager_t *this, - TNC_IMV_Action_Recommendation rec); + TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval); /** * Notify all IMV instances diff --git a/src/libcharon/tnc/tnccs/tnccs.h b/src/libcharon/tnc/tnccs/tnccs.h index c5d6f5ef0..32f065f67 100644 --- a/src/libcharon/tnc/tnccs/tnccs.h +++ b/src/libcharon/tnc/tnccs/tnccs.h @@ -72,8 +72,9 @@ typedef tnccs_t* (*tnccs_constructor_t)(bool is_server); * @param msg message to be added * @param msg_len message length * @param msg_type message type + * @return result code */ -typedef void (*tnccs_send_message_t)(tnccs_t* tncss, TNC_IMCID imc_id, +typedef TNC_Result (*tnccs_send_message_t)(tnccs_t* tncss, TNC_IMCID imc_id, TNC_IMVID imv_id, TNC_BufferReference msg, TNC_UInt32 msg_len, diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.c b/src/libcharon/tnc/tnccs/tnccs_manager.c index 7e522b870..609742dc8 100644 --- a/src/libcharon/tnc/tnccs/tnccs_manager.c +++ b/src/libcharon/tnc/tnccs/tnccs_manager.c @@ -215,11 +215,28 @@ METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID, } METHOD(tnccs_manager_t, remove_connection, void, - private_tnccs_manager_t *this, TNC_ConnectionID id) + private_tnccs_manager_t *this, TNC_ConnectionID id, bool is_server) { enumerator_t *enumerator; tnccs_connection_entry_t *entry; + if (is_server) + { + if (charon->imvs) + { + charon->imvs->notify_connection_change(charon->imvs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + else + { + if (charon->imcs) + { + charon->imcs->notify_connection_change(charon->imcs, id, + TNC_CONNECTION_STATE_DELETE); + } + } + this->connection_lock->write_lock(this->connection_lock); enumerator = this->connections->create_enumerator(this->connections); while (enumerator->enumerate(enumerator, &entry)) @@ -254,8 +271,8 @@ METHOD(tnccs_manager_t, request_handshake_retry, TNC_Result, } else { - DBG2(DBG_TNC, "%s %u requests handshake retry for connection ID %u " - "(reason: %u)", is_imc ? "IMC":"IMV", id, reason); + DBG2(DBG_TNC, "%s %u requests handshake retry for Connection ID %u " + "(reason: %u)", is_imc ? "IMC":"IMV", imcv_id, id, reason); } this->connection_lock->read_lock(this->connection_lock); enumerator = this->connections->create_enumerator(this->connections); @@ -279,11 +296,23 @@ METHOD(tnccs_manager_t, send_message, TNC_Result, TNC_BufferReference msg, TNC_UInt32 msg_len, TNC_MessageType msg_type) + { enumerator_t *enumerator; tnccs_connection_entry_t *entry; tnccs_send_message_t send_message = NULL; tnccs_t *tnccs = NULL; + TNC_VendorID msg_vid; + TNC_MessageSubtype msg_subtype; + + msg_vid = (msg_type >> 8) & TNC_VENDORID_ANY; + msg_subtype = msg_type & TNC_SUBTYPE_ANY; + + if (msg_vid == TNC_VENDORID_ANY || msg_subtype == TNC_SUBTYPE_ANY) + { + DBG1(DBG_TNC, "not sending message of invalid type 0x%08x", msg_type); + return TNC_RESULT_INVALID_PARAMETER; + } this->connection_lock->read_lock(this->connection_lock); enumerator = this->connections->create_enumerator(this->connections); @@ -301,9 +330,8 @@ METHOD(tnccs_manager_t, send_message, TNC_Result, if (tnccs && send_message) { - send_message(tnccs, imc_id, imv_id, msg, msg_len, msg_type); - return TNC_RESULT_SUCCESS; - } + return send_message(tnccs, imc_id, imv_id, msg, msg_len, msg_type); + } return TNC_RESULT_FATAL; } diff --git a/src/libcharon/tnc/tnccs/tnccs_manager.h b/src/libcharon/tnc/tnccs/tnccs_manager.h index c02eac03c..34f60029d 100644 --- a/src/libcharon/tnc/tnccs/tnccs_manager.h +++ b/src/libcharon/tnc/tnccs/tnccs_manager.h @@ -82,8 +82,10 @@ struct tnccs_manager_t { * Remove a TNCCS connection using its connection ID. * * @param id ID of the connection to be removed + * @param is_server TNC Server if TRUE, TNC Client if FALSE */ - void (*remove_connection)(tnccs_manager_t *this, TNC_ConnectionID id); + void (*remove_connection)(tnccs_manager_t *this, TNC_ConnectionID id, + bool is_server); /** * Request a handshake retry |