diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-08-09 08:09:54 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-08-09 08:09:54 +0000 |
commit | b8064f4099997a9e2179f3ad4ace605f5ccac3a1 (patch) | |
tree | 81778e976b476374c48b4fe83d084b986b890421 /src/libcharon | |
parent | 1ac70afcc1f7d6d2738a34308810719b0976d29f (diff) | |
download | vyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.tar.gz vyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.zip |
[svn-upgrade] new version strongswan (4.4.1)
Diffstat (limited to 'src/libcharon')
188 files changed, 7443 insertions, 6787 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index d473b455e..3297654e9 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -12,7 +12,6 @@ config/child_cfg.c config/child_cfg.h \ config/ike_cfg.c config/ike_cfg.h \ config/peer_cfg.c config/peer_cfg.h \ config/proposal.c config/proposal.h \ -config/auth_cfg.c config/auth_cfg.h \ control/controller.c control/controller.h \ daemon.c daemon.h \ encoding/generator.c encoding/generator.h \ @@ -95,17 +94,13 @@ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \ 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 \ -credentials/credential_manager.c credentials/credential_manager.h \ -credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \ -credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \ -credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ -credentials/credential_set.h +sa/tasks/task.c sa/tasks/task.h # adding the plugin source files LOCAL_SRC_FILES += $(call add_plugin, android) -ifneq ($(call plugin_enabled, android)),) +ifneq ($(call plugin_enabled, android),) +LOCAL_C_INCLUDES += frameworks/base/cmds/keystore LOCAL_SHARED_LIBRARIES += libcutils endif @@ -114,7 +109,7 @@ LOCAL_SRC_FILES += $(call add_plugin, attr) LOCAL_SRC_FILES += $(call add_plugin, eap-aka) LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2) -ifneq ($(call plugin_enabled, eap-aka-3gpp2)),) +ifneq ($(call plugin_enabled, eap-aka-3gpp2),) LOCAL_C_INCLUDES += $(libgmp_PATH) LOCAL_SHARED_LIBRARIES += libgmp endif @@ -129,6 +124,8 @@ LOCAL_SRC_FILES += $(call add_plugin, eap-mschapv2) LOCAL_SRC_FILES += $(call add_plugin, eap-sim) +LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-sql) + LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-pseudonym) LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-reauth) @@ -146,6 +143,8 @@ endif LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink) +LOCAL_SRC_FILES += $(call add_plugin, kernel-pfkey) + LOCAL_SRC_FILES += $(call add_plugin, load-tester) LOCAL_SRC_FILES += $(call add_plugin, socket-default) diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 0eaccf7a0..44501c0d0 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -10,7 +10,6 @@ config/child_cfg.c config/child_cfg.h \ config/ike_cfg.c config/ike_cfg.h \ config/peer_cfg.c config/peer_cfg.h \ config/proposal.c config/proposal.h \ -config/auth_cfg.c config/auth_cfg.h \ control/controller.c control/controller.h \ daemon.c daemon.h \ encoding/generator.c encoding/generator.h \ @@ -93,12 +92,7 @@ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \ 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 \ -credentials/credential_manager.c credentials/credential_manager.h \ -credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \ -credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \ -credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ -credentials/credential_set.h +sa/tasks/task.c sa/tasks/task.h daemon.lo : $(top_builddir)/config.status @@ -128,7 +122,7 @@ if USE_ME sa/tasks/ike_me.c sa/tasks/ike_me.h endif -if USE_CAPABILITIES +if USE_LIBCAP libcharon_la_LIBADD += -lcap endif @@ -271,6 +265,14 @@ if MONOLITHIC endif endif +if USE_EAP_SIMAKA_SQL + SUBDIRS += plugins/eap_simaka_sql + PLUGINS += eap-simaka-sql +if MONOLITHIC + libcharon_la_LIBADD += plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la +endif +endif + if USE_EAP_SIMAKA_PSEUDONYM SUBDIRS += plugins/eap_simaka_pseudonym PLUGINS += eap-simaka-pseudonym @@ -374,14 +376,6 @@ if MONOLITHIC endif endif -if USE_RESOLVE - SUBDIRS += plugins/resolve - PLUGINS += resolve -if MONOLITHIC - libcharon_la_LIBADD += plugins/resolve/libstrongswan-resolve.la -endif -endif - if USE_ANDROID SUBDIRS += plugins/android PLUGINS += android @@ -406,6 +400,14 @@ if MONOLITHIC endif endif +if USE_ADDRBLOCK + SUBDIRS += plugins/addrblock + PLUGINS += addrblock +if MONOLITHIC + libcharon_la_LIBADD += plugins/uci/libstrongswan-addrblock.la +endif +endif + if USE_UNIT_TESTS SUBDIRS += plugins/unit_tester PLUGINS += unit-tester diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in index 0eb6f36f4..8e58b0e2e 100644 --- a/src/libcharon/Makefile.in +++ b/src/libcharon/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -44,7 +44,7 @@ host_triplet = @host@ @USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \ @USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h -@USE_CAPABILITIES_TRUE@am__append_2 = -lcap +@USE_LIBCAP_TRUE@am__append_2 = -lcap @USE_LOAD_TESTER_TRUE@am__append_3 = plugins/load_tester @USE_LOAD_TESTER_TRUE@am__append_4 = load-tester @MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE@am__append_5 = plugins/load_tester/libstrongswan-load-tester.la @@ -93,46 +93,46 @@ host_triplet = @host@ @USE_EAP_SIM_FILE_TRUE@am__append_48 = plugins/eap_sim_file @USE_EAP_SIM_FILE_TRUE@am__append_49 = eap-sim-file @MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_50 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la -@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_51 = plugins/eap_simaka_pseudonym -@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_52 = eap-simaka-pseudonym -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_53 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la -@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_54 = plugins/eap_simaka_reauth -@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_55 = eap-simaka-reauth -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_56 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la -@USE_EAP_AKA_TRUE@am__append_57 = plugins/eap_aka -@USE_EAP_AKA_TRUE@am__append_58 = eap-aka -@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_59 = plugins/eap_aka/libstrongswan-eap-aka.la -@USE_EAP_AKA_3GPP2_TRUE@am__append_60 = plugins/eap_aka_3gpp2 -@USE_EAP_AKA_3GPP2_TRUE@am__append_61 = eap-aka-3gpp2 -@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_62 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la -@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_63 = $(top_builddir)/src/libsimaka/libsimaka.la -@USE_EAP_MD5_TRUE@am__append_64 = plugins/eap_md5 -@USE_EAP_MD5_TRUE@am__append_65 = eap-md5 -@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_66 = plugins/eap_md5/libstrongswan-eap-md5.la -@USE_EAP_GTC_TRUE@am__append_67 = plugins/eap_gtc -@USE_EAP_GTC_TRUE@am__append_68 = eap-gtc -@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_69 = plugins/eap_gtc/libstrongswan-eap-gtc.la -@USE_EAP_MSCHAPV2_TRUE@am__append_70 = plugins/eap_mschapv2 -@USE_EAP_MSCHAPV2_TRUE@am__append_71 = eap-mschapv2 -@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_72 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la -@USE_EAP_RADIUS_TRUE@am__append_73 = plugins/eap_radius -@USE_EAP_RADIUS_TRUE@am__append_74 = eap-radius -@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_75 = plugins/eap_radius/libstrongswan-eap-radius.la -@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv -@USE_MEDSRV_TRUE@am__append_77 = medsrv -@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_78 = plugins/medsrv/libstrongswan-medsrv.la -@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli -@USE_MEDCLI_TRUE@am__append_80 = medcli -@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_81 = plugins/medcli/libstrongswan-medcli.la -@USE_NM_TRUE@am__append_82 = plugins/nm -@USE_NM_TRUE@am__append_83 = nm -@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_84 = plugins/nm/libstrongswan-nm.la -@USE_DHCP_TRUE@am__append_85 = plugins/dhcp -@USE_DHCP_TRUE@am__append_86 = dhcp -@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_87 = plugins/dhcp/libstrongswan-dhcp.la -@USE_RESOLVE_TRUE@am__append_88 = plugins/resolve -@USE_RESOLVE_TRUE@am__append_89 = resolve -@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_90 = plugins/resolve/libstrongswan-resolve.la +@USE_EAP_SIMAKA_SQL_TRUE@am__append_51 = plugins/eap_simaka_sql +@USE_EAP_SIMAKA_SQL_TRUE@am__append_52 = eap-simaka-sql +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_53 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la +@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_54 = plugins/eap_simaka_pseudonym +@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_55 = eap-simaka-pseudonym +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_56 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la +@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_57 = plugins/eap_simaka_reauth +@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_58 = eap-simaka-reauth +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_59 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la +@USE_EAP_AKA_TRUE@am__append_60 = plugins/eap_aka +@USE_EAP_AKA_TRUE@am__append_61 = eap-aka +@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_62 = plugins/eap_aka/libstrongswan-eap-aka.la +@USE_EAP_AKA_3GPP2_TRUE@am__append_63 = plugins/eap_aka_3gpp2 +@USE_EAP_AKA_3GPP2_TRUE@am__append_64 = eap-aka-3gpp2 +@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_65 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la +@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_66 = $(top_builddir)/src/libsimaka/libsimaka.la +@USE_EAP_MD5_TRUE@am__append_67 = plugins/eap_md5 +@USE_EAP_MD5_TRUE@am__append_68 = eap-md5 +@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_69 = plugins/eap_md5/libstrongswan-eap-md5.la +@USE_EAP_GTC_TRUE@am__append_70 = plugins/eap_gtc +@USE_EAP_GTC_TRUE@am__append_71 = eap-gtc +@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_72 = plugins/eap_gtc/libstrongswan-eap-gtc.la +@USE_EAP_MSCHAPV2_TRUE@am__append_73 = plugins/eap_mschapv2 +@USE_EAP_MSCHAPV2_TRUE@am__append_74 = eap-mschapv2 +@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_75 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la +@USE_EAP_RADIUS_TRUE@am__append_76 = plugins/eap_radius +@USE_EAP_RADIUS_TRUE@am__append_77 = eap-radius +@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_78 = plugins/eap_radius/libstrongswan-eap-radius.la +@USE_MEDSRV_TRUE@am__append_79 = plugins/medsrv +@USE_MEDSRV_TRUE@am__append_80 = medsrv +@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_81 = plugins/medsrv/libstrongswan-medsrv.la +@USE_MEDCLI_TRUE@am__append_82 = plugins/medcli +@USE_MEDCLI_TRUE@am__append_83 = medcli +@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_84 = plugins/medcli/libstrongswan-medcli.la +@USE_NM_TRUE@am__append_85 = plugins/nm +@USE_NM_TRUE@am__append_86 = nm +@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_87 = plugins/nm/libstrongswan-nm.la +@USE_DHCP_TRUE@am__append_88 = plugins/dhcp +@USE_DHCP_TRUE@am__append_89 = dhcp +@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_90 = plugins/dhcp/libstrongswan-dhcp.la @USE_ANDROID_TRUE@am__append_91 = plugins/android @USE_ANDROID_TRUE@am__append_92 = android @MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_93 = plugins/android/libstrongswan-android.la @@ -142,9 +142,12 @@ host_triplet = @host@ @USE_UCI_TRUE@am__append_97 = plugins/uci @USE_UCI_TRUE@am__append_98 = uci @MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_99 = plugins/uci/libstrongswan-uci.la -@USE_UNIT_TESTS_TRUE@am__append_100 = plugins/unit_tester -@USE_UNIT_TESTS_TRUE@am__append_101 = unit-tester -@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_102 = plugins/unit_tester/libstrongswan-unit-tester.la +@USE_ADDRBLOCK_TRUE@am__append_100 = plugins/addrblock +@USE_ADDRBLOCK_TRUE@am__append_101 = addrblock +@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_102 = plugins/uci/libstrongswan-addrblock.la +@USE_UNIT_TESTS_TRUE@am__append_103 = plugins/unit_tester +@USE_UNIT_TESTS_TRUE@am__append_104 = unit-tester +@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_105 = plugins/unit_tester/libstrongswan-unit-tester.la subdir = src/libcharon DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -194,11 +197,11 @@ libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__append_38) $(am__append_41) $(am__append_44) \ $(am__append_47) $(am__append_50) $(am__append_53) \ $(am__append_56) $(am__append_59) $(am__append_62) \ - $(am__append_63) $(am__append_66) $(am__append_69) \ + $(am__append_65) $(am__append_66) $(am__append_69) \ $(am__append_72) $(am__append_75) $(am__append_78) \ $(am__append_81) $(am__append_84) $(am__append_87) \ $(am__append_90) $(am__append_93) $(am__append_96) \ - $(am__append_99) $(am__append_102) + $(am__append_99) $(am__append_102) $(am__append_105) 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 \ @@ -206,11 +209,10 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ config/backend_manager.h config/backend.h config/child_cfg.c \ config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \ config/peer_cfg.c config/peer_cfg.h config/proposal.c \ - config/proposal.h config/auth_cfg.c config/auth_cfg.h \ - control/controller.c control/controller.h daemon.c daemon.h \ - encoding/generator.c encoding/generator.h encoding/message.c \ - encoding/message.h encoding/parser.c encoding/parser.h \ - encoding/payloads/auth_payload.c \ + config/proposal.h control/controller.c control/controller.h \ + daemon.c daemon.h encoding/generator.c encoding/generator.h \ + encoding/message.c encoding/message.h encoding/parser.c \ + encoding/parser.h encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ encoding/payloads/cert_payload.h \ @@ -311,14 +313,6 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ 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 \ - credentials/credential_manager.c \ - credentials/credential_manager.h \ - credentials/sets/auth_cfg_wrapper.c \ - credentials/sets/auth_cfg_wrapper.h \ - credentials/sets/ocsp_response_wrapper.c \ - credentials/sets/ocsp_response_wrapper.h \ - credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ - credentials/credential_set.h \ encoding/payloads/endpoint_notify.c \ encoding/payloads/endpoint_notify.h \ processing/jobs/initiate_mediation_job.c \ @@ -332,32 +326,31 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ @USE_ME_TRUE@ connect_manager.lo mediation_manager.lo ike_me.lo am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \ backend_manager.lo child_cfg.lo ike_cfg.lo peer_cfg.lo \ - proposal.lo auth_cfg.lo controller.lo daemon.lo generator.lo \ - message.lo parser.lo auth_payload.lo cert_payload.lo \ - certreq_payload.lo configuration_attribute.lo cp_payload.lo \ - delete_payload.lo eap_payload.lo encodings.lo \ - encryption_payload.lo id_payload.lo ike_header.lo \ - ke_payload.lo nonce_payload.lo notify_payload.lo payload.lo \ - proposal_substructure.lo sa_payload.lo \ - traffic_selector_substructure.lo transform_attribute.lo \ - transform_substructure.lo ts_payload.lo unknown_payload.lo \ - vendor_id_payload.lo kernel_interface.lo kernel_ipsec.lo \ - packet.lo receiver.lo sender.lo socket_manager.lo \ - acquire_job.lo callback_job.lo delete_child_sa_job.lo \ - delete_ike_sa_job.lo migrate_job.lo process_message_job.lo \ - rekey_child_sa_job.lo rekey_ike_sa_job.lo retransmit_job.lo \ - send_dpd_job.lo send_keepalive_job.lo roam_job.lo \ - update_sa_job.lo inactivity_job.lo scheduler.lo processor.lo \ - authenticator.lo eap_authenticator.lo eap_method.lo \ - eap_manager.lo sim_manager.lo psk_authenticator.lo \ - pubkey_authenticator.lo child_sa.lo ike_sa.lo ike_sa_id.lo \ - ike_sa_manager.lo task_manager.lo keymat.lo trap_manager.lo \ - child_create.lo child_delete.lo child_rekey.lo ike_auth.lo \ - ike_cert_pre.lo ike_cert_post.lo ike_config.lo ike_delete.lo \ - ike_dpd.lo ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \ + proposal.lo controller.lo daemon.lo generator.lo message.lo \ + parser.lo auth_payload.lo cert_payload.lo certreq_payload.lo \ + configuration_attribute.lo cp_payload.lo delete_payload.lo \ + eap_payload.lo encodings.lo encryption_payload.lo \ + id_payload.lo ike_header.lo ke_payload.lo nonce_payload.lo \ + notify_payload.lo payload.lo proposal_substructure.lo \ + sa_payload.lo traffic_selector_substructure.lo \ + transform_attribute.lo transform_substructure.lo ts_payload.lo \ + unknown_payload.lo vendor_id_payload.lo kernel_interface.lo \ + kernel_ipsec.lo packet.lo receiver.lo sender.lo \ + socket_manager.lo acquire_job.lo callback_job.lo \ + delete_child_sa_job.lo delete_ike_sa_job.lo migrate_job.lo \ + process_message_job.lo rekey_child_sa_job.lo \ + rekey_ike_sa_job.lo retransmit_job.lo send_dpd_job.lo \ + send_keepalive_job.lo roam_job.lo update_sa_job.lo \ + inactivity_job.lo scheduler.lo processor.lo authenticator.lo \ + eap_authenticator.lo eap_method.lo eap_manager.lo \ + sim_manager.lo psk_authenticator.lo pubkey_authenticator.lo \ + child_sa.lo ike_sa.lo ike_sa_id.lo ike_sa_manager.lo \ + task_manager.lo keymat.lo trap_manager.lo child_create.lo \ + child_delete.lo child_rekey.lo ike_auth.lo ike_cert_pre.lo \ + ike_cert_post.lo ike_config.lo ike_delete.lo ike_dpd.lo \ + ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \ ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \ - credential_manager.lo auth_cfg_wrapper.lo \ - ocsp_response_wrapper.lo cert_cache.lo $(am__objects_1) + $(am__objects_1) libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -394,12 +387,12 @@ DIST_SUBDIRS = . plugins/load_tester plugins/kernel_pfkey \ 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_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/medsrv plugins/medcli plugins/nm plugins/dhcp \ - plugins/resolve plugins/android plugins/ha plugins/uci \ - plugins/unit_tester + 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/medsrv \ + plugins/medcli plugins/nm plugins/dhcp plugins/android \ + plugins/ha plugins/uci plugins/addrblock plugins/unit_tester DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -589,10 +582,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ config/backend.h config/child_cfg.c config/child_cfg.h \ config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \ config/peer_cfg.h config/proposal.c config/proposal.h \ - config/auth_cfg.c config/auth_cfg.h control/controller.c \ - control/controller.h daemon.c daemon.h encoding/generator.c \ - encoding/generator.h encoding/message.c encoding/message.h \ - encoding/parser.c encoding/parser.h \ + control/controller.c control/controller.h daemon.c daemon.h \ + encoding/generator.c encoding/generator.h encoding/message.c \ + encoding/message.h encoding/parser.c encoding/parser.h \ encoding/payloads/auth_payload.c \ encoding/payloads/auth_payload.h \ encoding/payloads/cert_payload.c \ @@ -694,14 +686,7 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ 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 \ - credentials/credential_manager.c \ - credentials/credential_manager.h \ - credentials/sets/auth_cfg_wrapper.c \ - credentials/sets/auth_cfg_wrapper.h \ - credentials/sets/ocsp_response_wrapper.c \ - credentials/sets/ocsp_response_wrapper.h \ - credentials/sets/cert_cache.c credentials/sets/cert_cache.h \ - credentials/credential_set.h $(am__append_1) + $(am__append_1) INCLUDES = \ -I${linux_headers} \ -I$(top_srcdir)/src/libstrongswan \ @@ -718,11 +703,11 @@ libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \ $(am__append_38) $(am__append_41) $(am__append_44) \ $(am__append_47) $(am__append_50) $(am__append_53) \ $(am__append_56) $(am__append_59) $(am__append_62) \ - $(am__append_63) $(am__append_66) $(am__append_69) \ + $(am__append_65) $(am__append_66) $(am__append_69) \ $(am__append_72) $(am__append_75) $(am__append_78) \ $(am__append_81) $(am__append_84) $(am__append_87) \ $(am__append_90) $(am__append_93) $(am__append_96) \ - $(am__append_99) $(am__append_102) + $(am__append_99) $(am__append_102) $(am__append_105) EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_6) \ @MONOLITHIC_FALSE@ $(am__append_9) $(am__append_12) \ @@ -734,13 +719,13 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_45) $(am__append_48) \ @MONOLITHIC_FALSE@ $(am__append_51) $(am__append_54) \ @MONOLITHIC_FALSE@ $(am__append_57) $(am__append_60) \ -@MONOLITHIC_FALSE@ $(am__append_64) $(am__append_67) \ +@MONOLITHIC_FALSE@ $(am__append_63) $(am__append_67) \ @MONOLITHIC_FALSE@ $(am__append_70) $(am__append_73) \ @MONOLITHIC_FALSE@ $(am__append_76) $(am__append_79) \ @MONOLITHIC_FALSE@ $(am__append_82) $(am__append_85) \ @MONOLITHIC_FALSE@ $(am__append_88) $(am__append_91) \ @MONOLITHIC_FALSE@ $(am__append_94) $(am__append_97) \ -@MONOLITHIC_FALSE@ $(am__append_100) +@MONOLITHIC_FALSE@ $(am__append_100) $(am__append_103) # build optional plugins ######################## @@ -754,13 +739,13 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_45) $(am__append_48) \ @MONOLITHIC_TRUE@ $(am__append_51) $(am__append_54) \ @MONOLITHIC_TRUE@ $(am__append_57) $(am__append_60) \ -@MONOLITHIC_TRUE@ $(am__append_64) $(am__append_67) \ +@MONOLITHIC_TRUE@ $(am__append_63) $(am__append_67) \ @MONOLITHIC_TRUE@ $(am__append_70) $(am__append_73) \ @MONOLITHIC_TRUE@ $(am__append_76) $(am__append_79) \ @MONOLITHIC_TRUE@ $(am__append_82) $(am__append_85) \ @MONOLITHIC_TRUE@ $(am__append_88) $(am__append_91) \ @MONOLITHIC_TRUE@ $(am__append_94) $(am__append_97) \ -@MONOLITHIC_TRUE@ $(am__append_100) +@MONOLITHIC_TRUE@ $(am__append_100) $(am__append_103) PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins} $(am__append_4) \ $(am__append_7) $(am__append_10) $(am__append_13) \ $(am__append_16) $(am__append_19) $(am__append_22) \ @@ -768,11 +753,11 @@ PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins} $(am__append_4) \ $(am__append_34) $(am__append_37) $(am__append_40) \ $(am__append_43) $(am__append_46) $(am__append_49) \ $(am__append_52) $(am__append_55) $(am__append_58) \ - $(am__append_61) $(am__append_65) $(am__append_68) \ + $(am__append_61) $(am__append_64) $(am__append_68) \ $(am__append_71) $(am__append_74) $(am__append_77) \ $(am__append_80) $(am__append_83) $(am__append_86) \ $(am__append_89) $(am__append_92) $(am__append_95) \ - $(am__append_98) $(am__append_101) + $(am__append_98) $(am__append_101) $(am__append_104) all: all-recursive .SUFFIXES: @@ -848,14 +833,11 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg_wrapper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certreq_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_cfg.Plo@am__quote@ @@ -867,7 +849,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp_payload.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Plo@am__quote@ @@ -913,7 +894,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Plo@am__quote@ @@ -1025,13 +1005,6 @@ proposal.lo: config/proposal.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal.lo `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c -auth_cfg.lo: config/auth_cfg.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.lo -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/auth_cfg.c' object='auth_cfg.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c - controller.lo: control/controller.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.lo -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.lo `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Plo @@ -1592,34 +1565,6 @@ task.lo: sa/tasks/task.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c -credential_manager.lo: credentials/credential_manager.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.lo -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c - -auth_cfg_wrapper.lo: credentials/sets/auth_cfg_wrapper.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.lo -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c - -ocsp_response_wrapper.lo: credentials/sets/ocsp_response_wrapper.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.lo -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c - -cert_cache.lo: credentials/sets/cert_cache.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.lo -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c - endpoint_notify.lo: encoding/payloads/endpoint_notify.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.lo -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/endpoint_notify.Tpo $(DEPDIR)/endpoint_notify.Plo @@ -1675,7 +1620,7 @@ clean-libtool: # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): - @failcom='exit 1'; \ + @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ @@ -1700,7 +1645,7 @@ $(RECURSIVE_TARGETS): fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): - @failcom='exit 1'; \ + @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c index 764744a41..441009e5e 100644 --- a/src/libcharon/bus/bus.c +++ b/src/libcharon/bus/bus.c @@ -102,20 +102,16 @@ static void entry_destroy(entry_t *entry) free(entry); } -/** - * Implementation of bus_t.add_listener. - */ -static void add_listener(private_bus_t *this, listener_t *listener) +METHOD(bus_t, add_listener, void, + private_bus_t *this, listener_t *listener) { this->mutex->lock(this->mutex); this->listeners->insert_last(this->listeners, entry_create(listener, FALSE)); this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.remove_listener. - */ -static void remove_listener(private_bus_t *this, listener_t *listener) +METHOD(bus_t, remove_listener, void, + private_bus_t *this, listener_t *listener) { enumerator_t *enumerator; entry_t *entry; @@ -156,10 +152,8 @@ static void listener_cleanup(cleanup_data_t *data) entry_destroy(data->entry); } -/** - * Implementation of bus_t.listen. - */ -static void listen_(private_bus_t *this, listener_t *listener, job_t *job) +METHOD(bus_t, listen_, void, + private_bus_t *this, listener_t *listener, job_t *job) { bool old; cleanup_data_t data; @@ -184,18 +178,14 @@ static void listen_(private_bus_t *this, listener_t *listener, job_t *job) entry_destroy(data.entry); } -/** - * Implementation of bus_t.set_sa. - */ -static void set_sa(private_bus_t *this, ike_sa_t *ike_sa) +METHOD(bus_t, set_sa, void, + private_bus_t *this, ike_sa_t *ike_sa) { this->thread_sa->set(this->thread_sa, ike_sa); } -/** - * Implementation of bus_t.get_sa - */ -static ike_sa_t* get_sa(private_bus_t *this) +METHOD(bus_t, get_sa, ike_sa_t*, + private_bus_t *this) { return this->thread_sa->get(this->thread_sa); } @@ -252,11 +242,9 @@ static bool log_cb(entry_t *entry, log_data_t *data) return FALSE; } -/** - * Implementation of bus_t.vlog. - */ -static void vlog(private_bus_t *this, debug_t group, level_t level, - char* format, va_list args) +METHOD(bus_t, vlog, void, + private_bus_t *this, debug_t group, level_t level, + char* format, va_list args) { log_data_t data; @@ -276,11 +264,8 @@ static void vlog(private_bus_t *this, debug_t group, level_t level, va_end(data.args); } -/** - * Implementation of bus_t.log. - */ -static void log_(private_bus_t *this, debug_t group, level_t level, - char* format, ...) +METHOD(bus_t, log_, void, + private_bus_t *this, debug_t group, level_t level, char* format, ...) { va_list args; @@ -307,10 +292,8 @@ static void unregister_listener(private_bus_t *this, entry_t *entry, this->listeners->remove_at(this->listeners, enumerator); } -/** - * Implementation of bus_t.alert - */ -static void alert(private_bus_t *this, alert_t alert, ...) +METHOD(bus_t, alert, void, + private_bus_t *this, alert_t alert, ...) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -342,11 +325,8 @@ static void alert(private_bus_t *this, alert_t alert, ...) this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.ike_state_change - */ -static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa, - ike_sa_state_t state) +METHOD(bus_t, ike_state_change, void, + private_bus_t *this, ike_sa_t *ike_sa, ike_sa_state_t state) { enumerator_t *enumerator; entry_t *entry; @@ -372,11 +352,8 @@ static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa, this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.child_state_change - */ -static void child_state_change(private_bus_t *this, child_sa_t *child_sa, - child_sa_state_t state) +METHOD(bus_t, child_state_change, void, + private_bus_t *this, child_sa_t *child_sa, child_sa_state_t state) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -406,10 +383,8 @@ static void child_state_change(private_bus_t *this, child_sa_t *child_sa, this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.message - */ -static void message(private_bus_t *this, message_t *message, bool incoming) +METHOD(bus_t, message, void, + private_bus_t *this, message_t *message, bool incoming) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -439,12 +414,9 @@ static void message(private_bus_t *this, message_t *message, bool incoming) this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.ike_keys - */ -static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, - ike_sa_t *rekey) +METHOD(bus_t, ike_keys, void, + private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey) { enumerator_t *enumerator; entry_t *entry; @@ -471,11 +443,9 @@ static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa, this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.child_keys - */ -static void child_keys(private_bus_t *this, child_sa_t *child_sa, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) +METHOD(bus_t, child_keys, void, + private_bus_t *this, child_sa_t *child_sa, bool initiator, + diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -494,7 +464,7 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa, } entry->calling++; keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa, - dh, nonce_i, nonce_r); + initiator, dh, nonce_i, nonce_r); entry->calling--; if (!keep) { @@ -505,10 +475,8 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa, this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.child_updown - */ -static void child_updown(private_bus_t *this, child_sa_t *child_sa, bool up) +METHOD(bus_t, child_updown, void, + private_bus_t *this, child_sa_t *child_sa, bool up) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -538,10 +506,8 @@ static void child_updown(private_bus_t *this, child_sa_t *child_sa, bool up) this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.child_rekey - */ -static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new) +METHOD(bus_t, child_rekey, void, + private_bus_t *this, child_sa_t *old, child_sa_t *new) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -570,10 +536,8 @@ static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new) this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.ike_updown - */ -static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up) +METHOD(bus_t, ike_updown, void, + private_bus_t *this, ike_sa_t *ike_sa, bool up) { enumerator_t *enumerator; entry_t *entry; @@ -613,10 +577,8 @@ static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up) } } -/** - * Implementation of bus_t.ike_rekey - */ -static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new) +METHOD(bus_t, ike_rekey, void, + private_bus_t *this, ike_sa_t *old, ike_sa_t *new) { enumerator_t *enumerator; entry_t *entry; @@ -642,10 +604,8 @@ static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new) this->mutex->unlock(this->mutex); } -/** - * Implementation of bus_t.authorize - */ -static bool authorize(private_bus_t *this, bool final) +METHOD(bus_t, authorize, bool, + private_bus_t *this, bool final) { enumerator_t *enumerator; ike_sa_t *ike_sa; @@ -680,10 +640,40 @@ static bool authorize(private_bus_t *this, bool final) return success; } -/** - * Implementation of bus_t.destroy. - */ -static void destroy(private_bus_t *this) +METHOD(bus_t, narrow, void, + private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type, + linked_list_t *local, linked_list_t *remote) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + entry_t *entry; + bool keep; + + ike_sa = this->thread_sa->get(this->thread_sa); + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->narrow) + { + continue; + } + entry->calling++; + keep = entry->listener->narrow(entry->listener, ike_sa, child_sa, + type, local, remote); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +METHOD(bus_t, destroy, void, + private_bus_t *this) { this->thread_sa->destroy(this->thread_sa); this->mutex->destroy(this->mutex); @@ -696,31 +686,35 @@ static void destroy(private_bus_t *this) */ bus_t *bus_create() { - private_bus_t *this = malloc_thing(private_bus_t); - - this->public.add_listener = (void(*)(bus_t*,listener_t*))add_listener; - this->public.remove_listener = (void(*)(bus_t*,listener_t*))remove_listener; - this->public.listen = (void(*)(bus_t*, listener_t *listener, job_t *job))listen_; - this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa; - this->public.get_sa = (ike_sa_t*(*)(bus_t*))get_sa; - this->public.log = (void(*)(bus_t*,debug_t,level_t,char*,...))log_; - this->public.vlog = (void(*)(bus_t*,debug_t,level_t,char*,va_list))vlog; - this->public.alert = (void(*)(bus_t*, alert_t alert, ...))alert; - this->public.ike_state_change = (void(*)(bus_t*,ike_sa_t*,ike_sa_state_t))ike_state_change; - this->public.child_state_change = (void(*)(bus_t*,child_sa_t*,child_sa_state_t))child_state_change; - this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message; - this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys; - this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys; - this->public.ike_updown = (void(*)(bus_t*, ike_sa_t *ike_sa, bool up))ike_updown; - this->public.ike_rekey = (void(*)(bus_t*, ike_sa_t *old, ike_sa_t *new))ike_rekey; - this->public.child_updown = (void(*)(bus_t*, child_sa_t *child_sa, bool up))child_updown; - this->public.child_rekey = (void(*)(bus_t*, child_sa_t *old, child_sa_t *new))child_rekey; - this->public.authorize = (bool(*)(bus_t*, bool final))authorize; - this->public.destroy = (void(*)(bus_t*)) destroy; - - this->listeners = linked_list_create(); - this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE); - this->thread_sa = thread_value_create(NULL); + private_bus_t *this; + + INIT(this, + .public = { + .add_listener = _add_listener, + .remove_listener = _remove_listener, + .listen = _listen_, + .set_sa = _set_sa, + .get_sa = _get_sa, + .log = _log_, + .vlog = _vlog, + .alert = _alert, + .ike_state_change = _ike_state_change, + .child_state_change = _child_state_change, + .message = _message, + .ike_keys = _ike_keys, + .child_keys = _child_keys, + .ike_updown = _ike_updown, + .ike_rekey = _ike_rekey, + .child_updown = _child_updown, + .child_rekey = _child_rekey, + .authorize = _authorize, + .narrow = _narrow, + .destroy = _destroy, + }, + .listeners = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + .thread_sa = thread_value_create(NULL), + ); return &this->public; } diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h index 8cf392eae..6a306afcc 100644 --- a/src/libcharon/bus/bus.h +++ b/src/libcharon/bus/bus.h @@ -22,6 +22,7 @@ #define BUS_H_ typedef enum alert_t alert_t; +typedef enum narrow_hook_t narrow_hook_t; typedef struct bus_t bus_t; #include <stdarg.h> @@ -86,6 +87,31 @@ enum alert_t { }; /** + * Kind of narrow hook. + * + * There is a non-authenticated (IKE_AUTH) and a authenticated + * (CREATE_CHILD_SA) narrowing hook for the initiator. Only one of these + * hooks is invoked before the exchange. + * To verify the traffic selectors negotiated, each PRE hook has a POST + * counterpart that follows. POST hooks are invoked with an authenticated peer. + * It is usually not a good idea to narrow in the POST hooks, + * as the resulting traffic selector is not negotiated and results + * in non-matching policies. + */ +enum narrow_hook_t { + /** invoked as initiator before exchange, peer is not yet authenticated */ + NARROW_INITIATOR_PRE_NOAUTH, + /** invoked as initiator before exchange, peer is authenticated */ + NARROW_INITIATOR_PRE_AUTH, + /** invoked as responder during exchange, peer is authenticated */ + NARROW_RESPONDER, + /** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */ + NARROW_INITIATOR_POST_NOAUTH, + /** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */ + NARROW_INITIATOR_POST_AUTH, +}; + +/** * The bus receives events and sends them to all registered listeners. * * Any events sent to are delivered to all registered listeners. Threads @@ -217,6 +243,17 @@ struct bus_t { bool (*authorize)(bus_t *this, bool final); /** + * CHILD_SA traffic selector narrowing hook. + * + * @param child_sa CHILD_SA set up with these traffic selectors + * @param type type of hook getting invoked + * @param local list of local traffic selectors to narrow + * @param remote list of remote traffic selectors to narrow + */ + void (*narrow)(bus_t *this, child_sa_t *child_sa, narrow_hook_t type, + linked_list_t *local, linked_list_t *remote); + + /** * IKE_SA keymat hook. * * @param ike_sa IKE_SA this keymat belongs to @@ -231,12 +268,13 @@ struct bus_t { * CHILD_SA keymat hook. * * @param child_sa CHILD_SA this keymat is used for + * @param initiator initiator of the CREATE_CHILD_SA exchange * @param dh diffie hellman shared secret * @param nonce_i initiators nonce * @param nonce_r responders nonce */ - void (*child_keys)(bus_t *this, child_sa_t *child_sa, diffie_hellman_t *dh, - chunk_t nonce_i, chunk_t nonce_r); + void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator, + diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r); /** * IKE_SA up/down hook. diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c index 12587deaf..87db532f5 100644 --- a/src/libcharon/bus/listeners/file_logger.c +++ b/src/libcharon/bus/listeners/file_logger.c @@ -15,6 +15,7 @@ #include <stdio.h> #include <string.h> +#include <time.h> #include "file_logger.h" @@ -40,6 +41,11 @@ struct private_file_logger_t { * Maximum level to log, for each group */ level_t levels[DBG_MAX]; + + /** + * strftime() format of time prefix, if any + */ + char *time_format; }; /** @@ -50,8 +56,17 @@ static bool log_(private_file_logger_t *this, debug_t group, level_t level, { if (level <= this->levels[group]) { - char buffer[8192]; + char buffer[8192], timestr[128]; char *current = buffer, *next; + struct tm tm; + time_t t; + + if (this->time_format) + { + t = time(NULL); + localtime_r(&t, &tm); + strftime(timestr, sizeof(timestr), this->time_format, &tm); + } /* write in memory buffer first */ vsnprintf(buffer, sizeof(buffer), format, args); @@ -64,8 +79,16 @@ static bool log_(private_file_logger_t *this, debug_t group, level_t level, { *(next++) = '\0'; } - fprintf(this->out, "%.2d[%N] %s\n", - thread, debug_names, group, current); + if (this->time_format) + { + fprintf(this->out, "%s %.2d[%N] %s\n", + timestr, thread, debug_names, group, current); + } + else + { + fprintf(this->out, "%.2d[%N] %s\n", + thread, debug_names, group, current); + } current = next; } } @@ -106,7 +129,7 @@ static void destroy(private_file_logger_t *this) /* * Described in header. */ -file_logger_t *file_logger_create(FILE *out) +file_logger_t *file_logger_create(FILE *out, char *time_format) { private_file_logger_t *this = malloc_thing(private_file_logger_t); @@ -118,6 +141,7 @@ file_logger_t *file_logger_create(FILE *out) /* private variables */ this->out = out; + this->time_format = time_format; set_level(this, DBG_ANY, LEVEL_SILENT); return &this->public; diff --git a/src/libcharon/bus/listeners/file_logger.h b/src/libcharon/bus/listeners/file_logger.h index bd443fdb8..e02a12c0c 100644 --- a/src/libcharon/bus/listeners/file_logger.h +++ b/src/libcharon/bus/listeners/file_logger.h @@ -52,9 +52,10 @@ struct file_logger_t { /** * Constructor to create a file_logger_t object. * - * @param out FILE to write to - * @return file_logger_t object + * @param out FILE to write to + * @param time_format format of timestamp prefix, as in strftime() + * @return file_logger_t object */ -file_logger_t *file_logger_create(FILE *out); +file_logger_t *file_logger_create(FILE *out, char *time_format); #endif /** FILE_LOGGER_H_ @}*/ diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h index 9a51a2ef4..e7873ee8c 100644 --- a/src/libcharon/bus/listeners/listener.h +++ b/src/libcharon/bus/listeners/listener.h @@ -110,13 +110,15 @@ struct listener_t { * * @param ike_sa IKE_SA the child sa belongs to * @param child_sa CHILD_SA this keymat is used for + * @param initiator initiator of the CREATE_CHILD_SA exchange * @param dh diffie hellman shared secret * @param nonce_i initiators nonce * @param nonce_r responders nonce * @return TRUE to stay registered, FALSE to unregister */ bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r); + bool initiator, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r); /** * Hook called if an IKE_SA gets up or down. @@ -173,6 +175,21 @@ struct listener_t { */ bool (*authorize)(listener_t *this, ike_sa_t *ike_sa, bool final, bool *success); + + /** + * CHILD_SA traffic selector narrowing hook. + * + * This hook is invoked for each CHILD_SA and allows plugins to modify + * the traffic selector list negotiated for this CHILD_SA. + * + * @param ike_sa IKE_SA the created CHILD_SA is created in + * @param child_sa CHILD_SA set up with these traffic selectors + * @param type type of hook getting invoked + * @param local list of local traffic selectors to narrow + * @param remote list of remote traffic selectors to narrow + */ + bool (*narrow)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + narrow_hook_t type, linked_list_t *local, linked_list_t *remote); }; #endif /** LISTENER_H_ @}*/ diff --git a/src/libcharon/bus/listeners/sys_logger.c b/src/libcharon/bus/listeners/sys_logger.c index 11421ad05..5bc1d581a 100644 --- a/src/libcharon/bus/listeners/sys_logger.c +++ b/src/libcharon/bus/listeners/sys_logger.c @@ -15,6 +15,7 @@ #include <stdio.h> #include <string.h> +#include <syslog.h> #include "sys_logger.h" diff --git a/src/libcharon/bus/listeners/sys_logger.h b/src/libcharon/bus/listeners/sys_logger.h index 730890d68..58d4de529 100644 --- a/src/libcharon/bus/listeners/sys_logger.h +++ b/src/libcharon/bus/listeners/sys_logger.h @@ -21,8 +21,6 @@ #ifndef SYS_LOGGER_H_ #define SYS_LOGGER_H_ -#include <syslog.h> - #include <bus/listeners/listener.h> typedef struct sys_logger_t sys_logger_t; diff --git a/src/libcharon/config/auth_cfg.c b/src/libcharon/config/auth_cfg.c deleted file mode 100644 index 94362c756..000000000 --- a/src/libcharon/config/auth_cfg.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (C) 2007-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner - * 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 "auth_cfg.h" - -#include <daemon.h> -#include <utils/linked_list.h> -#include <utils/identification.h> -#include <credentials/certificates/certificate.h> - -ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL, - "RULE_IDENTITY", - "RULE_AUTH_CLASS", - "RULE_EAP_IDENTITY", - "RULE_EAP_TYPE", - "RULE_EAP_VENDOR", - "RULE_CA_CERT", - "RULE_IM_CERT", - "RULE_SUBJECT_CERT", - "RULE_CRL_VALIDATION", - "RULE_OCSP_VALIDATION", - "RULE_AC_GROUP", - "HELPER_IM_CERT", - "HELPER_SUBJECT_CERT", - "HELPER_IM_HASH_URL", - "HELPER_SUBJECT_HASH_URL", -); - -typedef struct private_auth_cfg_t private_auth_cfg_t; - -/** - * private data of item_set - */ -struct private_auth_cfg_t { - - /** - * public functions - */ - auth_cfg_t public; - - /** - * list of entry_t - */ - linked_list_t *entries; -}; - -typedef struct entry_t entry_t; - -struct entry_t { - /** rule type */ - auth_rule_t type; - /** associated value */ - void *value; -}; - -/** - * enumerator for auth_cfg_t.create_enumerator() - */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** inner enumerator from linked_list_t */ - enumerator_t *inner; - /** current entry */ - entry_t *current; -} entry_enumerator_t; - -/** - * enumerate function for item_enumerator_t - */ -static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value) -{ - entry_t *entry; - - if (this->inner->enumerate(this->inner, &entry)) - { - this->current = entry; - *type = entry->type; - *value = entry->value; - return TRUE; - } - return FALSE; -} - -/** - * destroy function for item_enumerator_t - */ -static void entry_enumerator_destroy(entry_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * Implementation of auth_cfg_t.create_enumerator. - */ -static enumerator_t* create_enumerator(private_auth_cfg_t *this) -{ - entry_enumerator_t *enumerator; - - enumerator = malloc_thing(entry_enumerator_t); - enumerator->inner = this->entries->create_enumerator(this->entries); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)entry_enumerator_destroy; - enumerator->current = NULL; - return &enumerator->public; -} - -/** - * Destroy the value associated with an entry - */ -static void destroy_entry_value(entry_t *entry) -{ - switch (entry->type) - { - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - { - identification_t *id = (identification_t*)entry->value; - id->destroy(id); - break; - } - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - { - certificate_t *cert = (certificate_t*)entry->value; - cert->destroy(cert); - break; - } - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - { - free(entry->value); - break; - } - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - break; - } -} - -/** - * Implementation of auth_cfg_t.replace. - */ -static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator, - auth_rule_t type, ...) -{ - if (enumerator->current) - { - va_list args; - - va_start(args, type); - - destroy_entry_value(enumerator->current); - enumerator->current->type = type; - switch (type) - { - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - /* integer type */ - enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int); - break; - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - /* pointer type */ - enumerator->current->value = va_arg(args, void*); - break; - } - va_end(args); - } -} - -/** - * Implementation of auth_cfg_t.get. - */ -static void* get(private_auth_cfg_t *this, auth_rule_t type) -{ - enumerator_t *enumerator; - void *current_value, *best_value = NULL; - auth_rule_t current_type; - bool found = FALSE; - - enumerator = create_enumerator(this); - while (enumerator->enumerate(enumerator, ¤t_type, ¤t_value)) - { - if (type == current_type) - { - if (type == AUTH_RULE_CRL_VALIDATION || - type == AUTH_RULE_OCSP_VALIDATION) - { /* for CRL/OCSP validation, always get() the highest value */ - if (!found || current_value > best_value) - { - best_value = current_value; - } - found = TRUE; - continue; - } - best_value = current_value; - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - if (found) - { - return best_value; - } - switch (type) - { - /* use some sane defaults if we don't find an entry */ - case AUTH_RULE_AUTH_CLASS: - return (void*)AUTH_CLASS_ANY; - case AUTH_RULE_EAP_TYPE: - return (void*)EAP_NAK; - case AUTH_RULE_EAP_VENDOR: - return (void*)0; - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - return (void*)VALIDATION_FAILED; - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - default: - return NULL; - } -} - -/** - * Implementation of auth_cfg_t.add. - */ -static void add(private_auth_cfg_t *this, auth_rule_t type, ...) -{ - entry_t *entry = malloc_thing(entry_t); - va_list args; - - va_start(args, type); - entry->type = type; - switch (type) - { - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - /* integer type */ - entry->value = (void*)(uintptr_t)va_arg(args, u_int); - break; - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - /* pointer type */ - entry->value = va_arg(args, void*); - break; - } - va_end(args); - this->entries->insert_last(this->entries, entry); -} - -/** - * Implementation of auth_cfg_t.complies. - */ -static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints, - bool log_error) -{ - enumerator_t *e1, *e2; - bool success = TRUE; - auth_rule_t t1, t2; - void *value; - - e1 = constraints->create_enumerator(constraints); - while (e1->enumerate(e1, &t1, &value)) - { - switch (t1) - { - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - { - certificate_t *c1, *c2; - - c1 = (certificate_t*)value; - - success = FALSE; - e2 = create_enumerator(this); - while (e2->enumerate(e2, &t2, &c2)) - { - if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) && - c1->equals(c1, c2)) - { - success = TRUE; - } - } - e2->destroy(e2); - if (!success && log_error) - { - DBG1(DBG_CFG, "constraint check failed: peer not " - "authenticated by CA '%Y'.", c1->get_subject(c1)); - } - break; - } - case AUTH_RULE_SUBJECT_CERT: - { - certificate_t *c1, *c2; - - c1 = (certificate_t*)value; - c2 = get(this, AUTH_RULE_SUBJECT_CERT); - if (!c2 || !c1->equals(c1, c2)) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint check failed: peer not " - "authenticated with peer cert '%Y'.", - c1->get_subject(c1)); - } - } - break; - } - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - { - cert_validation_t validated, required; - - required = (uintptr_t)value; - validated = (uintptr_t)get(this, t1); - switch (required) - { - case VALIDATION_FAILED: - /* no constraint */ - break; - case VALIDATION_SKIPPED: - if (validated == VALIDATION_SKIPPED) - { - break; - } - /* FALL */ - case VALIDATION_GOOD: - if (validated == VALIDATION_GOOD) - { - break; - } - /* FALL */ - default: - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint check failed: %N is %N, " - "but requires at least %N", auth_rule_names, - t1, cert_validation_names, validated, - cert_validation_names, required); - } - break; - } - break; - } - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - { - identification_t *id1, *id2; - - id1 = (identification_t*)value; - id2 = get(this, t1); - if (!id2 || !id2->matches(id2, id1)) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'" - " required ", t1 == AUTH_RULE_IDENTITY ? "" : - "EAP ", id1); - } - } - break; - } - case AUTH_RULE_AUTH_CLASS: - { - if ((uintptr_t)value != AUTH_CLASS_ANY && - (uintptr_t)value != (uintptr_t)get(this, t1)) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires %N authentication, " - "but %N was used", auth_class_names, (uintptr_t)value, - auth_class_names, (uintptr_t)get(this, t1)); - } - } - break; - } - case AUTH_RULE_EAP_TYPE: - { - if ((uintptr_t)value != (uintptr_t)get(this, t1)) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires %N, " - "but %N was used", eap_type_names, (uintptr_t)value, - eap_type_names, (uintptr_t)get(this, t1)); - } - } - break; - } - case AUTH_RULE_EAP_VENDOR: - { - if ((uintptr_t)value != (uintptr_t)get(this, t1)) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires EAP vendor %d, " - "but %d was used", (uintptr_t)value, - (uintptr_t)get(this, t1)); - } - } - break; - } - case AUTH_RULE_AC_GROUP: - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint check %N not implemented!", - auth_rule_names, t1); - } - break; - } - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - /* skip helpers */ - continue; - } - if (!success) - { - break; - } - } - e1->destroy(e1); - return success; -} - -/** - * Implementation of auth_cfg_t.merge. - */ -static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy) -{ - if (!other) - { /* nothing to merge */ - return; - } - if (copy) - { - enumerator_t *enumerator; - auth_rule_t type; - void *value; - - enumerator = create_enumerator(other); - while (enumerator->enumerate(enumerator, &type, &value)) - { - switch (type) - { - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - { - certificate_t *cert = (certificate_t*)value; - - add(this, type, cert->get_ref(cert)); - break; - } - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - { - add(this, type, (uintptr_t)value); - break; - } - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - { - identification_t *id = (identification_t*)value; - - add(this, type, id->clone(id)); - break; - } - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - { - add(this, type, strdup((char*)value)); - break; - } - } - } - enumerator->destroy(enumerator); - } - else - { - entry_t *entry; - - while (other->entries->remove_first(other->entries, - (void**)&entry) == SUCCESS) - { - this->entries->insert_last(this->entries, entry); - } - } -} - -/** - * Implementation of auth_cfg_t.equals. - */ -static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) -{ - enumerator_t *e1, *e2; - entry_t *i1, *i2; - bool equal = TRUE, found; - - if (this->entries->get_count(this->entries) != - other->entries->get_count(other->entries)) - { - return FALSE; - } - e1 = this->entries->create_enumerator(this->entries); - while (e1->enumerate(e1, &i1)) - { - found = FALSE; - e2 = other->entries->create_enumerator(other->entries); - while (e2->enumerate(e2, &i2)) - { - if (i1->type == i2->type) - { - switch (i1->type) - { - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - { - if (i1->value == i2->value) - { - found = TRUE; - break; - } - continue; - } - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - { - certificate_t *c1, *c2; - - c1 = (certificate_t*)i1->value; - c2 = (certificate_t*)i2->value; - - if (c1->equals(c1, c2)) - { - found = TRUE; - break; - } - continue; - } - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - { - identification_t *id1, *id2; - - id1 = (identification_t*)i1->value; - id2 = (identification_t*)i2->value; - - if (id1->equals(id1, id2)) - { - found = TRUE; - break; - } - continue; - } - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - { - if (streq(i1->value, i2->value)) - { - found = TRUE; - break; - } - continue; - } - } - break; - } - } - e2->destroy(e2); - if (!found) - { - equal = FALSE; - break; - } - } - e1->destroy(e1); - return equal; -} - -/** - * Implementation of auth_cfg_t.purge - */ -static void purge(private_auth_cfg_t *this, bool keep_ca) -{ - entry_t *entry; - linked_list_t *cas; - - cas = linked_list_create(); - while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS) - { - if (keep_ca && entry->type == AUTH_RULE_CA_CERT) - { - cas->insert_first(cas, entry); - } - else - { - destroy_entry_value(entry); - free(entry); - } - } - while (cas->remove_last(cas, (void**)&entry) == SUCCESS) - { - this->entries->insert_first(this->entries, entry); - } - cas->destroy(cas); -} - -/** - * Implementation of auth_cfg_t.clone - */ -static auth_cfg_t* clone_(private_auth_cfg_t *this) -{ - enumerator_t *enumerator; - auth_cfg_t *clone; - entry_t *entry; - - clone = auth_cfg_create(); - enumerator = this->entries->create_enumerator(this->entries); - while (enumerator->enumerate(enumerator, &entry)) - { - switch (entry->type) - { - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AC_GROUP: - { - identification_t *id = (identification_t*)entry->value; - clone->add(clone, entry->type, id->clone(id)); - break; - } - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - { - certificate_t *cert = (certificate_t*)entry->value; - clone->add(clone, entry->type, cert->get_ref(cert)); - break; - } - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - { - clone->add(clone, entry->type, strdup(entry->value)); - break; - } - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - clone->add(clone, entry->type, (uintptr_t)entry->value); - break; - } - } - enumerator->destroy(enumerator); - return clone; -} - -/** - * Implementation of auth_cfg_t.destroy - */ -static void destroy(private_auth_cfg_t *this) -{ - purge(this, FALSE); - this->entries->destroy(this->entries); - free(this); -} - -/* - * see header file - */ -auth_cfg_t *auth_cfg_create() -{ - private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t); - - this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add; - this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get; - this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator; - this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace; - this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies; - this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge; - this->public.purge = (void(*)(auth_cfg_t*,bool))purge; - this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals; - this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_; - this->public.destroy = (void(*)(auth_cfg_t*))destroy; - - this->entries = linked_list_create(); - - return &this->public; -} - diff --git a/src/libcharon/config/auth_cfg.h b/src/libcharon/config/auth_cfg.h deleted file mode 100644 index 5e6215a4a..000000000 --- a/src/libcharon/config/auth_cfg.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2007-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner - * 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 auth_cfg auth_cfg - * @{ @ingroup config - */ - -#ifndef AUTH_CFG_H_ -#define AUTH_CFG_H_ - -#include <utils/enumerator.h> - -typedef struct auth_cfg_t auth_cfg_t; -typedef enum auth_rule_t auth_rule_t; - -/** - * Authentication config to use during authentication process. - * - * Each authentication config contains a set of rules. These rule-sets are used - * in two ways: - * - For configs specifying local authentication behavior, the rules define - * which authentication method in which way. - * - For configs specifying remote peer authentication, the rules define - * constraints the peer has to fullfill. - * - * Additionally to the rules, there is a set of helper items. These are used - * to transport credentials during the authentication process. - */ -enum auth_rule_t { - - /** identity to use for IKEv2 authentication exchange, identification_t* */ - AUTH_RULE_IDENTITY, - /** authentication class, auth_class_t */ - AUTH_RULE_AUTH_CLASS, - /** EAP identity to use within EAP-Identity exchange, identification_t* */ - AUTH_RULE_EAP_IDENTITY, - /** EAP type to propose for peer authentication, eap_type_t */ - AUTH_RULE_EAP_TYPE, - /** EAP vendor for vendor specific type, u_int32_t */ - AUTH_RULE_EAP_VENDOR, - /** certificate authority, certificate_t* */ - AUTH_RULE_CA_CERT, - /** intermediate certificate in trustchain, certificate_t* */ - AUTH_RULE_IM_CERT, - /** subject certificate, certificate_t* */ - AUTH_RULE_SUBJECT_CERT, - /** result of a CRL validation, cert_validation_t */ - AUTH_RULE_CRL_VALIDATION, - /** result of a OCSP validation, cert_validation_t */ - AUTH_RULE_OCSP_VALIDATION, - /** subject is in attribute certificate group, identification_t* */ - AUTH_RULE_AC_GROUP, - - /** intermediate certificate, certificate_t* */ - AUTH_HELPER_IM_CERT, - /** subject certificate, certificate_t* */ - AUTH_HELPER_SUBJECT_CERT, - /** Hash and URL of a intermediate certificate, char* */ - AUTH_HELPER_IM_HASH_URL, - /** Hash and URL of a end-entity certificate, char* */ - AUTH_HELPER_SUBJECT_HASH_URL, -}; - -/** - * enum name for auth_rule_t. - */ -extern enum_name_t *auth_rule_names; - -/** - * Authentication/Authorization round. - * - * RFC4739 defines multiple authentication rounds. This class defines such - * a round from a configuration perspective, either for the local or the remote - * peer. Local config are called "rulesets", as they define how we authenticate. - * Remote peer configs are called "constraits", they define what is needed to - * complete the authentication round successfully. - * - * @verbatim - - [Repeat for each configuration] - +--------------------------------------------------+ - | | - | | - | +----------+ IKE_AUTH +--------- + | - | | config | -----------> | | | - | | ruleset | | | | - | +----------+ [ <----------- ] | | | - | [ optional EAP ] | Peer | | - | +----------+ [ -----------> ] | | | - | | config | | | | - | | constr. | <----------- | | | - | +----------+ IKE_AUTH +--------- + | - | | - | | - +--------------------------------------------------+ - - @endverbatim - * - * Values for each items are either pointers (casted to void*) or short - * integers (use uintptr_t cast). - */ -struct auth_cfg_t { - - /** - * Add an rule to the set. - * - * @param rule rule type - * @param ... associated value to rule - */ - void (*add)(auth_cfg_t *this, auth_rule_t rule, ...); - - /** - * Get an rule value. - * - * @param rule rule type - * @return bool if item has been found - */ - void* (*get)(auth_cfg_t *this, auth_rule_t rule); - - /** - * Create an enumerator over added rules. - * - * @return enumerator over (auth_rule_t, union{void*,uintpr_t}) - */ - enumerator_t* (*create_enumerator)(auth_cfg_t *this); - - /** - * Replace an rule at enumerator position. - * - * @param pos enumerator position position - * @param rule rule type - * @param ... associated value to rule - */ - void (*replace)(auth_cfg_t *this, enumerator_t *pos, - auth_rule_t rule, ...); - - /** - * Check if a used config fulfills a set of configured constraints. - * - * @param constraints required authorization rules - * @param log_error wheter to log compliance errors - * @return TRUE if this complies with constraints - */ - bool (*complies)(auth_cfg_t *this, auth_cfg_t *constraints, bool log_error); - - /** - * Merge items from other into this. - * - * @param other items to read for merge - * @param copy TRUE to copy items, FALSE to move them - */ - void (*merge)(auth_cfg_t *this, auth_cfg_t *other, bool copy); - - /** - * Purge all rules in a config. - * - * @param keep_ca wheter to keep AUTH_RULE_CA_CERT entries - */ - void (*purge)(auth_cfg_t *this, bool keep_ca); - - /** - * Check two configs for equality. - * - * @param other other config to compaire against this - * @return TRUE if auth infos identical - */ - bool (*equals)(auth_cfg_t *this, auth_cfg_t *other); - - /** - * Clone a authentication config, including all rules. - * - * @return cloned configuration - */ - auth_cfg_t* (*clone)(auth_cfg_t *this); - - /** - * Destroy a config with all associated rules/values. - */ - void (*destroy)(auth_cfg_t *this); -}; - -/** - * Create a authentication config. - */ -auth_cfg_t *auth_cfg_create(); - -#endif /** AUTH_CFG_H_ @}*/ diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index 8410b3fe5..70f38b285 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -17,6 +17,8 @@ #include "child_cfg.h" +#include <stdint.h> + #include <daemon.h> ENUM(action_names, ACTION_NONE, ACTION_RESTART, @@ -112,6 +114,20 @@ struct private_child_cfg_t { u_int32_t inactivity; /** + * Reqid to install CHILD_SA with + */ + u_int32_t reqid; + + /** + * Optional mark to install inbound CHILD_SA with + */ + mark_t mark_in; + + /** + * Optional mark to install outbound CHILD_SA with + */ + mark_t mark_out; + /** * set up IPsec transport SA in MIPv6 proxy mode */ bool proxy_mode; @@ -446,6 +462,22 @@ static u_int32_t get_inactivity(private_child_cfg_t *this) } /** + * Implementation of child_cfg_t.get_reqid. + */ +static u_int32_t get_reqid(private_child_cfg_t *this) +{ + return this->reqid; +} + +/** + * Implementation of child_cfg_t.get_mark. + */ +static mark_t get_mark(private_child_cfg_t *this, bool inbound) +{ + return inbound ? this->mark_in : this->mark_out; +} + +/** * Implementation of child_cfg_t.set_mipv6_options. */ static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode, @@ -506,7 +538,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, char *updown, bool hostaccess, ipsec_mode_t mode, action_t dpd_action, action_t close_action, bool ipcomp, - u_int32_t inactivity) + u_int32_t inactivity, u_int32_t reqid, + mark_t *mark_in, mark_t *mark_out) { private_child_cfg_t *this = malloc_thing(private_child_cfg_t); @@ -526,6 +559,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options; this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp; this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity; + this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid; + this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark; this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode; this->public.install_policy = (bool (*) (child_cfg_t *))install_policy; this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref; @@ -539,6 +574,27 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, this->close_action = close_action; this->use_ipcomp = ipcomp; this->inactivity = inactivity; + this->reqid = reqid; + + if (mark_in) + { + this->mark_in = *mark_in; + } + else + { + this->mark_in.value = 0; + this->mark_in.mask = 0; + } + if (mark_out) + { + this->mark_out = *mark_out; + } + else + { + this->mark_out.value = 0; + this->mark_out.mask = 0; + } + this->proxy_mode = FALSE; this->install_policy = TRUE; this->refcount = 1; diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h index c6186ea36..d34835ead 100644 --- a/src/libcharon/config/child_cfg.h +++ b/src/libcharon/config/child_cfg.h @@ -26,6 +26,7 @@ typedef enum action_t action_t; typedef enum ipcomp_transform_t ipcomp_transform_t; typedef struct lifetime_cfg_t lifetime_cfg_t; +typedef struct mark_t mark_t; typedef struct child_cfg_t child_cfg_t; #include <library.h> @@ -83,6 +84,16 @@ struct lifetime_cfg_t { }; /** + * A mark_t defines an optional mark in a CHILD_SA. + */ +struct mark_t { + /** Mark value */ + u_int32_t value; + /** Mark mask */ + u_int32_t mask; +}; + +/** * A child_cfg_t defines the config template for a CHILD_SA. * * After creation, proposals and traffic selectors may be added to the config. @@ -239,6 +250,21 @@ struct child_cfg_t { u_int32_t (*get_inactivity)(child_cfg_t *this); /** + * Specific reqid to use for CHILD_SA + * + * @return reqid + */ + u_int32_t (*get_reqid)(child_cfg_t *this); + + /** + * Optional mark for CHILD_SA + * + * @param inbound TRUE for inbound, FALSE for outbound + * @return mark + */ + mark_t (*get_mark)(child_cfg_t *this, bool inbound); + + /** * Sets two options needed for Mobile IPv6 interoperability * * @param proxy_mode use IPsec transport proxy mode (default FALSE) @@ -299,12 +325,16 @@ struct child_cfg_t { * @param close_action close action * @param ipcomp use IPComp, if peer supports it * @param inactivity inactivity timeout in s before closing a CHILD_SA - * @return child_cfg_t object + * @param reqid specific reqid to use for CHILD_SA, 0 for auto assign + * @param mark_in optional inbound mark (can be NULL) + * @param mark_out optional outbound mark (can be NULL) + * @return child_cfg_t object */ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, char *updown, bool hostaccess, ipsec_mode_t mode, action_t dpd_action, action_t close_action, bool ipcomp, - u_int32_t inactivity); + u_int32_t inactivity, u_int32_t reqid, + mark_t *mark_in, mark_t *mark_out); #endif /** CHILD_CFG_H_ @}*/ diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index 6855276f8..723435cbb 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -36,7 +36,7 @@ typedef struct peer_cfg_t peer_cfg_t; #include <config/child_cfg.h> #include <sa/authenticators/authenticator.h> #include <sa/authenticators/eap/eap_method.h> -#include <config/auth_cfg.h> +#include <credentials/auth_cfg.h> /** * Certificate sending policy. This is also used for certificate diff --git a/src/libcharon/credentials/credential_manager.c b/src/libcharon/credentials/credential_manager.c deleted file mode 100644 index adea0b4be..000000000 --- a/src/libcharon/credentials/credential_manager.c +++ /dev/null @@ -1,1681 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "credential_manager.h" - -#include <daemon.h> -#include <threading/thread_value.h> -#include <threading/mutex.h> -#include <threading/rwlock.h> -#include <utils/linked_list.h> -#include <credentials/sets/cert_cache.h> -#include <credentials/sets/auth_cfg_wrapper.h> -#include <credentials/sets/ocsp_response_wrapper.h> -#include <credentials/certificates/x509.h> -#include <credentials/certificates/crl.h> -#include <credentials/certificates/ocsp_request.h> -#include <credentials/certificates/ocsp_response.h> - -typedef struct private_credential_manager_t private_credential_manager_t; - -/** - * private data of credential_manager - */ -struct private_credential_manager_t { - - /** - * public functions - */ - credential_manager_t public; - - /** - * list of credential sets - */ - linked_list_t *sets; - - /** - * thread local set of credentials, linked_list_t with credential_set_t's - */ - thread_value_t *local_sets; - - /** - * trust relationship and certificate cache - */ - cert_cache_t *cache; - - /** - * certificates queued for persistent caching - */ - linked_list_t *cache_queue; - - /** - * read-write lock to sets list - */ - rwlock_t *lock; - - /** - * mutex for cache queue - */ - mutex_t *queue_mutex; -}; - -/** data to pass to create_private_enumerator */ -typedef struct { - private_credential_manager_t *this; - key_type_t type; - identification_t* keyid; -} private_data_t; - -/** data to pass to create_cert_enumerator */ -typedef struct { - private_credential_manager_t *this; - certificate_type_t cert; - key_type_t key; - identification_t *id; - bool trusted; -} cert_data_t; - -/** data to pass to create_cdp_enumerator */ -typedef struct { - private_credential_manager_t *this; - certificate_type_t type; - identification_t *id; -} cdp_data_t; - -/** data to pass to create_shared_enumerator */ -typedef struct { - private_credential_manager_t *this; - shared_key_type_t type; - identification_t *me; - identification_t *other; -} shared_data_t; - -/** enumerator over local and global sets */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** enumerator over global sets */ - enumerator_t *global; - /** enumerator over local sets */ - enumerator_t *local; -} sets_enumerator_t; - -/** - * destroy a sets_enumerator_t - */ -static void sets_enumerator_destroy(sets_enumerator_t *this) -{ - DESTROY_IF(this->global); - DESTROY_IF(this->local); - free(this); -} - -/** - * sets_enumerator_t.enumerate - */ -static bool sets_enumerator_enumerate(sets_enumerator_t *this, - credential_set_t **set) -{ - if (this->global) - { - if (this->global->enumerate(this->global, set)) - { - return TRUE; - } - /* end of global sets, look for local */ - this->global->destroy(this->global); - this->global = NULL; - } - if (this->local) - { - return this->local->enumerate(this->local, set); - } - return FALSE; -} - -/** - * create an enumerator over both, global and local sets - */ -static enumerator_t *create_sets_enumerator(private_credential_manager_t *this) -{ - linked_list_t *local; - sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t); - - enumerator->public.enumerate = (void*)sets_enumerator_enumerate; - enumerator->public.destroy = (void*)sets_enumerator_destroy; - enumerator->global = this->sets->create_enumerator(this->sets); - enumerator->local = NULL; - local = this->local_sets->get(this->local_sets); - if (local) - { - enumerator->local = local->create_enumerator(local); - } - return &enumerator->public; -} - -/** - * cleanup function for cert data - */ -static void destroy_cert_data(cert_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for certificates - */ -static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data) -{ - return set->create_cert_enumerator(set, data->cert, data->key, - data->id, data->trusted); -} - -/** - * Implementation of credential_manager_t.create_cert_enumerator. - */ -static enumerator_t *create_cert_enumerator(private_credential_manager_t *this, - certificate_type_t certificate, key_type_t key, - identification_t *id, bool trusted) -{ - cert_data_t *data = malloc_thing(cert_data_t); - data->this = this; - data->cert = certificate; - data->key = key; - data->id = id; - data->trusted = trusted; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_cert, data, - (void*)destroy_cert_data); -} - -/** - * Implementation of credential_manager_t.get_cert. - */ -static certificate_t *get_cert(private_credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - certificate_t *current, *found = NULL; - enumerator_t *enumerator; - - enumerator = create_cert_enumerator(this, cert, key, id, trusted); - if (enumerator->enumerate(enumerator, ¤t)) - { - /* TODO: best match? order by keyid, subject, sualtname */ - found = current->get_ref(current); - } - enumerator->destroy(enumerator); - return found; -} - - -/** - * cleanup function for cdp data - */ -static void destroy_cdp_data(cdp_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for CDPs - */ -static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data) -{ - return set->create_cdp_enumerator(set, data->type, data->id); -} -/** - * Implementation of credential_manager_t.create_cdp_enumerator. - */ -static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this, - certificate_type_t type, identification_t *id) -{ - cdp_data_t *data = malloc_thing(cdp_data_t); - data->this = this; - data->type = type; - data->id = id; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_cdp, data, - (void*)destroy_cdp_data); -} - -/** - * cleanup function for private data - */ -static void destroy_private_data(private_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for private keys - */ -static enumerator_t *create_private(credential_set_t *set, private_data_t *data) -{ - return set->create_private_enumerator(set, data->type, data->keyid); -} - -/** - * Implementation of credential_manager_t.create_private_enumerator. - */ -static enumerator_t* create_private_enumerator( - private_credential_manager_t *this, - key_type_t key, identification_t *keyid) -{ - private_data_t *data; - - data = malloc_thing(private_data_t); - data->this = this; - data->type = key; - data->keyid = keyid; - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_private, data, - (void*)destroy_private_data); -} - -/** - * Implementation of credential_manager_t.get_private_by_keyid. - */ -static private_key_t *get_private_by_keyid(private_credential_manager_t *this, - key_type_t key, identification_t *keyid) -{ - private_key_t *found = NULL; - enumerator_t *enumerator; - - enumerator = create_private_enumerator(this, key, keyid); - if (enumerator->enumerate(enumerator, &found)) - { - found->get_ref(found); - } - enumerator->destroy(enumerator); - return found; -} - -/** - * cleanup function for shared data - */ -static void destroy_shared_data(shared_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for shared keys - */ -static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data) -{ - return set->create_shared_enumerator(set, data->type, data->me, data->other); -} - -/** - * Implementation of credential_manager_t.create_shared_enumerator. - */ -static enumerator_t *create_shared_enumerator(private_credential_manager_t *this, - shared_key_type_t type, - identification_t *me, identification_t *other) -{ - shared_data_t *data = malloc_thing(shared_data_t); - data->this = this; - data->type = type; - data->me = me; - data->other = other; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_shared, data, - (void*)destroy_shared_data); -} - -/** - * Implementation of credential_manager_t.get_shared. - */ -static shared_key_t *get_shared(private_credential_manager_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) -{ - shared_key_t *current, *found = NULL; - id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE; - id_match_t *match_me, *match_other; - enumerator_t *enumerator; - - enumerator = create_shared_enumerator(this, type, me, other); - while (enumerator->enumerate(enumerator, ¤t, &match_me, &match_other)) - { - if (match_other > best_other || - (match_other == best_other && match_me > best_me)) - { - DESTROY_IF(found); - found = current->get_ref(current); - best_me = match_me; - best_other = match_other; - } - } - enumerator->destroy(enumerator); - return found; -} - -/** - * add a credential set to the thread local list - */ -static void add_local_set(private_credential_manager_t *this, - credential_set_t *set) -{ - linked_list_t *sets; - - sets = this->local_sets->get(this->local_sets); - if (!sets) - { /* first invocation */ - sets = linked_list_create(); - this->local_sets->set(this->local_sets, sets); - } - sets->insert_last(sets, set); -} - -/** - * remove a credential set from the thread local list - */ -static void remove_local_set(private_credential_manager_t *this, - credential_set_t *set) -{ - linked_list_t *sets; - - sets = this->local_sets->get(this->local_sets); - sets->remove(sets, set, NULL); -} - -/** - * Implementation of credential_manager_t.cache_cert. - */ -static void cache_cert(private_credential_manager_t *this, certificate_t *cert) -{ - credential_set_t *set; - enumerator_t *enumerator; - - if (this->lock->try_write_lock(this->lock)) - { - enumerator = this->sets->create_enumerator(this->sets); - while (enumerator->enumerate(enumerator, &set)) - { - set->cache_cert(set, cert); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - } - else - { /* we can't cache now as other threads are active, queue for later */ - this->queue_mutex->lock(this->queue_mutex); - this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert)); - this->queue_mutex->unlock(this->queue_mutex); - } -} - -/** - * Try to cache certificates queued for caching - */ -static void cache_queue(private_credential_manager_t *this) -{ - credential_set_t *set; - certificate_t *cert; - enumerator_t *enumerator; - - this->queue_mutex->lock(this->queue_mutex); - if (this->cache_queue->get_count(this->cache_queue) > 0 && - this->lock->try_write_lock(this->lock)) - { - while (this->cache_queue->remove_last(this->cache_queue, - (void**)&cert) == SUCCESS) - { - enumerator = this->sets->create_enumerator(this->sets); - while (enumerator->enumerate(enumerator, &set)) - { - set->cache_cert(set, cert); - } - enumerator->destroy(enumerator); - cert->destroy(cert); - } - this->lock->unlock(this->lock); - } - this->queue_mutex->unlock(this->queue_mutex); -} - -/** - * forward declaration - */ -static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, bool crl, bool ocsp); - -/** - * Do an OCSP request - */ -static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, - certificate_t *subject, certificate_t *issuer) -{ - certificate_t *request, *response; - chunk_t send, receive; - - /* TODO: requestor name, signature */ - request = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, - BUILD_CA_CERT, issuer, - BUILD_CERT, subject, BUILD_END); - if (!request) - { - DBG1(DBG_CFG, "generating ocsp request failed"); - return NULL; - } - - send = request->get_encoding(request); - request->destroy(request); - - DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &receive, - FETCH_REQUEST_DATA, send, - FETCH_REQUEST_TYPE, "application/ocsp-request", - FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "ocsp request to %s failed", url); - chunk_free(&send); - return NULL; - } - chunk_free(&send); - - response = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, - BUILD_BLOB_ASN1_DER, receive, BUILD_END); - chunk_free(&receive); - if (!response) - { - DBG1(DBG_CFG, "parsing ocsp response failed"); - return NULL; - } - return response; -} - -/** - * check the signature of an OCSP response - */ -static bool verify_ocsp(private_credential_manager_t *this, - ocsp_response_t *response) -{ - certificate_t *issuer, *subject; - identification_t *responder; - ocsp_response_wrapper_t *wrapper; - enumerator_t *enumerator; - bool verified = FALSE; - - wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); - add_local_set(this, &wrapper->set); - - subject = &response->certificate; - responder = subject->get_issuer(subject); - enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, subject, issuer)) - { - DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - remove_local_set(this, &wrapper->set); - wrapper->destroy(wrapper); - return verified; -} - -/** - * Get the better of two OCSP responses, and check for usable OCSP info - */ -static certificate_t *get_better_ocsp(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - ocsp_response_t *response; - time_t revocation, this_update, next_update, valid_until; - crl_reason_t reason; - bool revoked = FALSE; - - response = (ocsp_response_t*)cand; - - /* check ocsp signature */ - if (!verify_ocsp(this, response)) - { - DBG1(DBG_CFG, "ocsp response verification failed"); - cand->destroy(cand); - return best; - } - /* check if response contains our certificate */ - switch (response->get_status(response, subject, issuer, &revocation, &reason, - &this_update, &next_update)) - { - case VALIDATION_REVOKED: - /* subject has been revoked by a valid OCSP response */ - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - revoked = TRUE; - break; - case VALIDATION_GOOD: - /* results in either good or stale */ - break; - default: - case VALIDATION_FAILED: - /* candidate unusable, does not contain our cert */ - DBG1(DBG_CFG, " ocsp response contains no status on our certificate"); - cand->destroy(cand); - return best; - } - - /* select the better of the two responses */ - if (best == NULL || cand->is_newer(cand, best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " ocsp response is valid: until %T", - &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* cache non-stale only, stale certs get refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " ocsp response is stale: since %T", - &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - if (revoked) - { /* revoked always counts, even if stale */ - *valid = VALIDATION_REVOKED; - } - return best; -} - -/** - * validate a x509 certificate using OCSP - */ -static cert_validation_t check_ocsp(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - enumerator_t *enumerator; - cert_validation_t valid = VALIDATION_SKIPPED; - certificate_t *best = NULL, *current; - identification_t *keyid = NULL; - public_key_t *public; - chunk_t chunk; - char *uri = NULL; - - /** lookup cache for valid OCSP responses */ - enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE, - KEY_ANY, NULL, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached ocsp response"); - break; - } - } - enumerator->destroy(enumerator); - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - } - /** fetch from configured OCSP responder URLs */ - if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - DESTROY_IF(public); - DESTROY_IF(keyid); - - /* fallback to URL fetching from subject certificate's URIs */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_ocsp_uri_enumerator(subject); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid); - if (valid == VALIDATION_GOOD) - { /* successful OCSP check fulfills also CRL constraint */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD); - } - } - DESTROY_IF(best); - return valid; -} - -/** - * fetch a CRL from an URL - */ -static certificate_t* fetch_crl(private_credential_manager_t *this, char *url) -{ - certificate_t *crl; - chunk_t chunk; - - DBG1(DBG_CFG, " fetching crl from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "crl fetching failed"); - return NULL; - } - crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, - BUILD_BLOB_ASN1_DER, chunk, BUILD_END); - chunk_free(&chunk); - if (!crl) - { - DBG1(DBG_CFG, "crl fetched successfully but parsing failed"); - return NULL; - } - return crl; -} - -/** - * check the signature of an CRL - */ -static bool verify_crl(private_credential_manager_t *this, certificate_t *crl) -{ - certificate_t *issuer; - enumerator_t *enumerator; - bool verified = FALSE; - - enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl), - FALSE, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, crl, issuer)) - { - DBG1(DBG_CFG, " crl correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - return verified; -} - -/** - * Get the better of two CRLs, and check for usable CRL info - */ -static certificate_t *get_better_crl(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - enumerator_t *enumerator; - time_t revocation, valid_until; - crl_reason_t reason; - chunk_t serial; - crl_t *crl; - - /* check CRL signature */ - if (!verify_crl(this, cand)) - { - DBG1(DBG_CFG, "crl response verification failed"); - cand->destroy(cand); - return best; - } - - crl = (crl_t*)cand; - enumerator = crl->create_enumerator(crl); - while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) - { - if (chunk_equals(serial, subject->get_serial(subject))) - { - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - *valid = VALIDATION_REVOKED; - enumerator->destroy(enumerator); - DESTROY_IF(best); - return cand; - } - } - enumerator->destroy(enumerator); - - /* select the better of the two CRLs */ - if (best == NULL || cand->is_newer(cand, best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* we cache non-stale crls only, as a stale crls are refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - return best; -} - -/** - * validate a x509 certificate using CRL - */ -static cert_validation_t check_crl(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - cert_validation_t valid = VALIDATION_SKIPPED; - identification_t *keyid = NULL; - certificate_t *best = NULL; - certificate_t *current; - public_key_t *public; - enumerator_t *enumerator; - chunk_t chunk; - char *uri = NULL; - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - - /* find a cached crl by authorityKeyIdentifier */ - enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY, - keyid, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_crl(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached crl"); - break; - } - } - enumerator->destroy(enumerator); - - /* fallback to fetching crls from credential sets cdps */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - keyid->destroy(keyid); - } - DESTROY_IF(public); - - /* fallback to fetching crls from cdps from subject's certificate */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_crl_uri_enumerator(subject); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - if (valid == VALIDATION_SKIPPED) - { /* if we skipped CRL validation, we use the result of OCSP for - * constraint checking */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, - auth->get(auth, AUTH_RULE_OCSP_VALIDATION)); - } - else - { - auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid); - } - } - DESTROY_IF(best); - return valid; -} - -/** - * check a certificate for optional IP address block constraints - */ -static bool check_ip_addr_block_constraints(x509_t *subject, x509_t *issuer) -{ - bool subject_constraint = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS; - bool issuer_constraint = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS; - bool contained = TRUE; - - enumerator_t *subject_enumerator, *issuer_enumerator; - traffic_selector_t *subject_ts, *issuer_ts; - - if (!subject_constraint && !issuer_constraint) - { - return TRUE; - } - if (!subject_constraint) - { - DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension"); - return FALSE; - } - if (!issuer_constraint) - { - DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension"); - return FALSE; - } - subject_enumerator = subject->create_ipAddrBlock_enumerator(subject); - while (subject_enumerator->enumerate(subject_enumerator, &subject_ts)) - { - contained = FALSE; - - issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer); - while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts)) - { - if (subject_ts->is_contained_in(subject_ts, issuer_ts)) - { - DBG2(DBG_CFG, " subject address block %R is contained in " - "issuer address block %R", subject_ts, issuer_ts); - contained = TRUE; - break; - } - } - issuer_enumerator->destroy(issuer_enumerator); - if (!contained) - { - DBG1(DBG_CFG, "subject address block %R is not contained in any " - "issuer address block", subject_ts); - break; - } - } - subject_enumerator->destroy(subject_enumerator); - return contained; -} - -/** - * check a certificate for its lifetime - */ -static bool check_certificate(private_credential_manager_t *this, - certificate_t *subject, certificate_t *issuer, - bool crl, bool ocsp, auth_cfg_t *auth) -{ - time_t not_before, not_after; - - if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (issuer->get_type(issuer) == CERT_X509 && - subject->get_type(subject) == CERT_X509) - { - if (!check_ip_addr_block_constraints((x509_t*)subject, (x509_t*)issuer)) - { - return FALSE; - } - if (ocsp || crl) - { - DBG1(DBG_CFG, "checking certificate status of \"%Y\"", - subject->get_subject(subject)); - } - if (ocsp) - { - switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_SKIPPED: - DBG2(DBG_CFG, "ocsp check skipped, no ocsp found"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "ocsp information stale, fallback to crl"); - break; - case VALIDATION_FAILED: - DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); - break; - } - } - if (crl) - { - switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_FAILED: - case VALIDATION_SKIPPED: - DBG1(DBG_CFG, "certificate status is not available"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "certificate status is unknown, crl is stale"); - break; - } - } - } - return TRUE; -} - -/** - * Get a trusted certificate from a credential set - */ -static certificate_t *get_pretrusted_cert(private_credential_manager_t *this, - key_type_t type, identification_t *id) -{ - certificate_t *subject; - public_key_t *public; - - subject = get_cert(this, CERT_ANY, type, id, TRUE); - if (!subject) - { - return NULL; - } - public = subject->get_public_key(subject); - if (!public) - { - subject->destroy(subject); - return NULL; - } - public->destroy(public); - return subject; -} - -/** - * Get the issuing certificate of a subject certificate - */ -static certificate_t *get_issuer_cert(private_credential_manager_t *this, - certificate_t *subject, bool trusted) -{ - enumerator_t *enumerator; - certificate_t *issuer = NULL, *candidate; - - enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY, - subject->get_issuer(subject), trusted); - while (enumerator->enumerate(enumerator, &candidate)) - { - if (this->cache->issued_by(this->cache, subject, candidate)) - { - issuer = candidate->get_ref(candidate); - break; - } - } - enumerator->destroy(enumerator); - return issuer; -} - -/** - * try to verify the trust chain of subject, return TRUE if trusted - */ -static bool verify_trust_chain(private_credential_manager_t *this, - certificate_t *subject, auth_cfg_t *result, - bool trusted, bool crl, bool ocsp) -{ - certificate_t *current, *issuer; - x509_t *x509; - auth_cfg_t *auth; - int pathlen, pathlen_constraint; - - auth = auth_cfg_create(); - current = subject->get_ref(subject); - - for (pathlen = 0; pathlen <= X509_MAX_PATH_LEN; pathlen++) - { - issuer = get_issuer_cert(this, current, TRUE); - if (issuer) - { - /* accept only self-signed CAs as trust anchor */ - if (this->cache->issued_by(this->cache, issuer, issuer)) - { - auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"", - issuer->get_subject(issuer)); - trusted = TRUE; - } - else - { - auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using trusted intermediate ca certificate " - "\"%Y\"", issuer->get_subject(issuer)); - } - } - else - { - issuer = get_issuer_cert(this, current, FALSE); - if (issuer) - { - if (current->equals(current, issuer)) - { - DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted", - current->get_subject(current)); - issuer->destroy(issuer); - break; - } - auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using untrusted intermediate certificate " - "\"%Y\"", issuer->get_subject(issuer)); - } - else - { - DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"", - current->get_subject(current)); - break; - } - } - if (!check_certificate(this, current, issuer, crl, ocsp, - current == subject ? auth : NULL)) - { - trusted = FALSE; - issuer->destroy(issuer); - break; - } - - /* check path length constraint */ - x509 = (x509_t*)issuer; - pathlen_constraint = x509->get_pathLenConstraint(x509); - if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT && - pathlen > pathlen_constraint) - { - DBG1(DBG_CFG, "path length of %d violates constraint of %d", - pathlen, pathlen_constraint); - trusted = FALSE; - issuer->destroy(issuer); - break; - } - current->destroy(current); - current = issuer; - if (trusted) - { - DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d", - pathlen); - break; - } - } - current->destroy(current); - if (pathlen > X509_MAX_PATH_LEN) - { - DBG1(DBG_CFG, "maximum path length of %d exceeded", X509_MAX_PATH_LEN); - } - if (trusted) - { - result->merge(result, auth, FALSE); - } - auth->destroy(auth); - return trusted; -} - -/** - * enumerator for trusted certificates - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** enumerator over candidate peer certificates */ - enumerator_t *candidates; - /** reference to the credential_manager */ - private_credential_manager_t *this; - /** type of the requested key */ - key_type_t type; - /** identity the requested key belongs to */ - identification_t *id; - /** TRUE to do CRL checking */ - bool crl; - /** TRUE to do OCSP checking */ - bool ocsp; - /** pretrusted certificate we have served at first invocation */ - certificate_t *pretrusted; - /** currently enumerating auth config */ - auth_cfg_t *auth; -} trusted_enumerator_t; - -/** - * Implements trusted_enumerator_t.enumerate - */ -static bool trusted_enumerate(trusted_enumerator_t *this, - certificate_t **cert, auth_cfg_t **auth) -{ - certificate_t *current; - - DESTROY_IF(this->auth); - this->auth = auth_cfg_create(); - - if (!this->candidates) - { - /* first invocation, build enumerator for next one */ - this->candidates = create_cert_enumerator(this->this, CERT_ANY, - this->type, this->id, FALSE); - /* check if we have a trusted certificate for that peer */ - this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id); - if (this->pretrusted) - { - /* if we find a trusted self signed certificate, we just accept it. - * However, in order to fulfill authorization rules, we try to build - * the trust chain if it is not self signed */ - if (this->this->cache->issued_by(this->this->cache, - this->pretrusted, this->pretrusted) || - verify_trust_chain(this->this, this->pretrusted, this->auth, - TRUE, this->crl, this->ocsp)) - { - this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT, - this->pretrusted->get_ref(this->pretrusted)); - DBG1(DBG_CFG, " using trusted certificate \"%Y\"", - this->pretrusted->get_subject(this->pretrusted)); - *cert = this->pretrusted; - if (auth) - { - *auth = this->auth; - } - return TRUE; - } - } - } - /* try to verify the trust chain for each certificate found */ - while (this->candidates->enumerate(this->candidates, ¤t)) - { - if (this->pretrusted && - this->pretrusted->equals(this->pretrusted, current)) - { /* skip pretrusted certificate we already served */ - continue; - } - - DBG1(DBG_CFG, " using certificate \"%Y\"", - current->get_subject(current)); - if (verify_trust_chain(this->this, current, this->auth, FALSE, - this->crl, this->ocsp)) - { - *cert = current; - if (auth) - { - *auth = this->auth; - } - return TRUE; - } - } - return FALSE; -} - -/** - * Implements trusted_enumerator_t.destroy - */ -static void trusted_destroy(trusted_enumerator_t *this) -{ - DESTROY_IF(this->pretrusted); - DESTROY_IF(this->auth); - DESTROY_IF(this->candidates); - free(this); -} - -/** - * create an enumerator over trusted certificates and their trustchain - */ -static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, bool crl, bool ocsp) -{ - trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t); - - enumerator->public.enumerate = (void*)trusted_enumerate; - enumerator->public.destroy = (void*)trusted_destroy; - - enumerator->candidates = NULL; - enumerator->this = this; - enumerator->type = type; - enumerator->id = id; - enumerator->crl = crl; - enumerator->ocsp = ocsp; - enumerator->pretrusted = NULL; - enumerator->auth = NULL; - - return &enumerator->public; -} - -/** - * enumerator for public keys - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** enumerator over candidate peer certificates */ - enumerator_t *inner; - /** reference to the credential_manager */ - private_credential_manager_t *this; - /** currently enumerating key */ - public_key_t *current; - /** credset wrapper around auth config */ - auth_cfg_wrapper_t *wrapper; -} public_enumerator_t; - -/** - * Implements public_enumerator_t.enumerate - */ -static bool public_enumerate(public_enumerator_t *this, - public_key_t **key, auth_cfg_t **auth) -{ - certificate_t *cert; - - while (this->inner->enumerate(this->inner, &cert, auth)) - { - DESTROY_IF(this->current); - this->current = cert->get_public_key(cert); - if (this->current) - { - *key = this->current; - return TRUE; - } - } - return FALSE; -} - -/** - * Implements public_enumerator_t.destroy - */ -static void public_destroy(public_enumerator_t *this) -{ - DESTROY_IF(this->current); - this->inner->destroy(this->inner); - if (this->wrapper) - { - remove_local_set(this->this, &this->wrapper->set); - this->wrapper->destroy(this->wrapper); - } - this->this->lock->unlock(this->this->lock); - - /* check for delayed certificate cache queue */ - cache_queue(this->this); - free(this); -} - -/** - * Implementation of credential_manager_t.create_public_enumerator. - */ -static enumerator_t* create_public_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, auth_cfg_t *auth) -{ - public_enumerator_t *enumerator = malloc_thing(public_enumerator_t); - - enumerator->public.enumerate = (void*)public_enumerate; - enumerator->public.destroy = (void*)public_destroy; - enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE); - enumerator->this = this; - enumerator->current = NULL; - enumerator->wrapper = NULL; - if (auth) - { - enumerator->wrapper = auth_cfg_wrapper_create(auth); - add_local_set(this, &enumerator->wrapper->set); - } - this->lock->read_lock(this->lock); - return &enumerator->public; -} - -/** - * Check if a certificate's keyid is contained in the auth helper - */ -static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert) -{ - enumerator_t *enumerator; - identification_t *value; - auth_rule_t type; - bool found = FALSE; - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &value)) - { - if (type == AUTH_RULE_CA_CERT && - cert->equals(cert, (certificate_t*)value)) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - return found; -} - -/** - * build a trustchain from subject up to a trust anchor in trusted - */ -static auth_cfg_t *build_trustchain(private_credential_manager_t *this, - certificate_t *subject, auth_cfg_t *auth) -{ - certificate_t *issuer, *current; - auth_cfg_t *trustchain; - int pathlen = 0; - - trustchain = auth_cfg_create(); - - current = auth->get(auth, AUTH_RULE_CA_CERT); - if (!current) - { - /* no trust anchor specified, return this cert only */ - trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, - subject->get_ref(subject)); - return trustchain; - } - current = subject->get_ref(subject); - while (TRUE) - { - if (auth_contains_cacert(auth, current)) - { - trustchain->add(trustchain, AUTH_RULE_CA_CERT, current); - return trustchain; - } - if (subject == current) - { - trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current); - } - else - { - trustchain->add(trustchain, AUTH_RULE_IM_CERT, current); - } - issuer = get_issuer_cert(this, current, FALSE); - if (!issuer || issuer->equals(issuer, current) || - pathlen > X509_MAX_PATH_LEN) - { - DESTROY_IF(issuer); - break; - } - current = issuer; - pathlen++; - } - trustchain->destroy(trustchain); - return NULL; -} - -/** - * find a private key of a give certificate - */ -static private_key_t *get_private_by_cert(private_credential_manager_t *this, - certificate_t *cert, key_type_t type) -{ - private_key_t *private = NULL; - identification_t *keyid; - chunk_t chunk; - public_key_t *public; - - public = cert->get_public_key(cert); - if (public) - { - if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - private = get_private_by_keyid(this, type, keyid); - keyid->destroy(keyid); - } - public->destroy(public); - } - return private; -} - -/** - * Implementation of credential_manager_t.get_private. - */ -static private_key_t *get_private(private_credential_manager_t *this, - key_type_t type, identification_t *id, - auth_cfg_t *auth) -{ - enumerator_t *enumerator; - certificate_t *cert; - private_key_t *private = NULL; - auth_cfg_t *trustchain; - - /* check if this is a lookup by key ID, and do it if so */ - if (id && id->get_type(id) == ID_KEY_ID) - { - private = get_private_by_keyid(this, type, id); - if (private) - { - return private; - } - } - - /* if a specific certificate is preferred, check for a matching key */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (cert) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) - { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); - } - return private; - } - } - - /* try to build a trust chain for each certificate found */ - enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); - while (enumerator->enumerate(enumerator, &cert)) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) - { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); - break; - } - private->destroy(private); - private = NULL; - } - } - enumerator->destroy(enumerator); - - /* if no valid trustchain was found, fall back to the first usable cert */ - if (!private) - { - enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); - while (enumerator->enumerate(enumerator, &cert)) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert)); - break; - } - } - enumerator->destroy(enumerator); - } - return private; -} - -/** - * Implementation of credential_manager_t.flush_cache. - */ -static void flush_cache(private_credential_manager_t *this, - certificate_type_t type) -{ - this->cache->flush(this->cache, type); -} - -/** - * Implementation of credential_manager_t.add_set. - */ -static void add_set(private_credential_manager_t *this, - credential_set_t *set) -{ - this->lock->write_lock(this->lock); - this->sets->insert_last(this->sets, set); - this->lock->unlock(this->lock); -} - -/** - * Implementation of credential_manager_t.remove_set. - */ -static void remove_set(private_credential_manager_t *this, credential_set_t *set) -{ - this->lock->write_lock(this->lock); - this->sets->remove(this->sets, set, NULL); - this->lock->unlock(this->lock); -} - -/** - * Implementation of credential_manager_t.destroy - */ -static void destroy(private_credential_manager_t *this) -{ - cache_queue(this); - this->cache_queue->destroy(this->cache_queue); - this->sets->remove(this->sets, this->cache, NULL); - this->sets->destroy(this->sets); - this->local_sets->destroy(this->local_sets); - this->cache->destroy(this->cache); - this->lock->destroy(this->lock); - this->queue_mutex->destroy(this->queue_mutex); - free(this); -} - -/* - * see header file - */ -credential_manager_t *credential_manager_create() -{ - private_credential_manager_t *this = malloc_thing(private_credential_manager_t); - - this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator; - this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator; - this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator; - this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert; - this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared; - this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private; - this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator; - this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache; - this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert; - this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set; - this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set; - this->public.destroy = (void(*)(credential_manager_t*))destroy; - - this->sets = linked_list_create(); - this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy); - this->cache = cert_cache_create(); - this->cache_queue = linked_list_create(); - this->sets->insert_first(this->sets, this->cache); - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - this->queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT); - - return &this->public; -} - diff --git a/src/libcharon/credentials/credential_manager.h b/src/libcharon/credentials/credential_manager.h deleted file mode 100644 index 0448da992..000000000 --- a/src/libcharon/credentials/credential_manager.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2007-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 credential_manager credential_manager - * @{ @ingroup ccredentials - */ - -#ifndef CREDENTIAL_MANAGER_H_ -#define CREDENTIAL_MANAGER_H_ - -#include <utils/identification.h> -#include <utils/enumerator.h> -#include <config/auth_cfg.h> -#include <credentials/credential_set.h> -#include <credentials/keys/private_key.h> -#include <credentials/keys/shared_key.h> -#include <credentials/certificates/certificate.h> - -typedef struct credential_manager_t credential_manager_t; - -/** - * Manages credentials using credential_sets. - * - * The credential manager is the entry point of the credential framework. It - * uses so called "sets" to access credentials in a modular fashion, these - * are implemented through the credential_set_t interface. - * The manager additionally does trust chain verification and trust status - * chaching. A set may call the managers methods if it needs credentials itself, - * the manager uses recursive locking. - * - * @verbatim - - +-------+ +----------------+ - | A | | | +------------------+ - | u | -----> | | ------> | +------------------+ - | t | | credential- | | | +------------------+ - | h | -----> | manager | ------> +--| | credential- | => IPC - | e | | | +--| sets | - | n | +--> | | ------> +------------------+ - | t | | | | | - | i | | | | | - | c | | +----------------+ | - | a | | | - | t | +----------------------------------------------+ - | o | may be recursive - | r | - +-------+ - - @endverbatim - * - * The credential manager uses rwlocks for performance reasons, credential - * sets must be fully thread save. - */ -struct credential_manager_t { - - /** - * Create an enumerator over all certificates. - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id subject this certificate belongs to - * @param trusted TRUE to list trusted certificates only - * @return enumerator over the certificates - */ - enumerator_t *(*create_cert_enumerator)(credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Create an enumerator over all shared keys. - * - * The enumerator enumerates over: - * shared_key_t*, id_match_t me, id_match_t other - * But must accepts values for the id_matches. - * - * @param type kind of requested shared key - * @param first first subject between key is shared - * @param second second subject between key is shared - * @return enumerator over shared keys - */ - enumerator_t *(*create_shared_enumerator)(credential_manager_t *this, - shared_key_type_t type, - identification_t *first, identification_t *second); - /** - * Create an enumerator over all Certificate Distribution Points. - * - * @param type kind of certificate the point distributes - * @param id identification of the distributed certificate - * @return enumerator of CDPs as char* - */ - enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this, - certificate_type_t type, identification_t *id); - /** - * Get a trusted or untrusted certificate. - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id subject this certificate belongs to - * @param trusted TRUE to get a trusted certificate only - * @return certificate, if found, NULL otherwise - */ - certificate_t *(*get_cert)(credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Get the best matching shared key for two IDs. - * - * @param type kind of requested shared key - * @param me own identity - * @param other peers identity - * @return shared_key_t, NULL if none found - */ - shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type, - identification_t *me, identification_t *other); - /** - * Get a private key to create a signature. - * - * The get_private() method gets a secret private key identified by either - * the keyid itself or an id the key belongs to. - * The auth parameter contains additional information, such as receipients - * trusted CA certs. Auth gets filled with subject and CA certificates - * needed to validate a created signature. - * - * @param type type of the key to get - * @param id identification the key belongs to - * @param auth auth config, including trusted CA certificates - * @return private_key_t, NULL if none found - */ - private_key_t* (*get_private)(credential_manager_t *this, key_type_t type, - identification_t *id, auth_cfg_t *auth); - - /** - * Create an enumerator over trusted public keys. - * - * This method gets a an enumerator over trusted public keys to verify a - * signature created by id. The auth parameter contains additional - * authentication infos, e.g. peer and intermediate certificates. - * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *, - * where the auth config helper contains rules for constraint checks. - * - * @param type type of the key to get - * @param id owner of the key, signer of the signature - * @param auth authentication infos - * @return enumerator - */ - enumerator_t* (*create_public_enumerator)(credential_manager_t *this, - key_type_t type, identification_t *id, auth_cfg_t *auth); - - /** - * Cache a certificate by invoking cache_cert() on all registerd sets. - * - * @param cert certificate to cache - */ - void (*cache_cert)(credential_manager_t *this, certificate_t *cert); - - /** - * Flush the certificate cache. - * - * Only the managers local cache is flushed, but not the sets cache filled - * by the cache_cert() method. - * - * @param type type of certificate to flush, or CERT_ANY - */ - void (*flush_cache)(credential_manager_t *this, certificate_type_t type); - - /** - * Register a credential set to the manager. - * - * @param set set to register - */ - void (*add_set)(credential_manager_t *this, credential_set_t *set); - - /** - * Unregister a credential set from the manager. - * - * @param set set to unregister - */ - void (*remove_set)(credential_manager_t *this, credential_set_t *set); - - /** - * Destroy a credential_manager instance. - */ - void (*destroy)(credential_manager_t *this); -}; - -/** - * Create a credential_manager instance. - */ -credential_manager_t *credential_manager_create(); - -#endif /** CREDENTIAL_MANAGER_H_ @}*/ diff --git a/src/libcharon/credentials/credential_set.h b/src/libcharon/credentials/credential_set.h deleted file mode 100644 index 274eb3feb..000000000 --- a/src/libcharon/credentials/credential_set.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup credential_set credential_set - * @{ @ingroup ccredentials - */ - -#ifndef CREDENTIAL_SET_H_ -#define CREDENTIAL_SET_H_ - -#include <credentials/keys/public_key.h> -#include <credentials/keys/shared_key.h> -#include <credentials/certificates/certificate.h> - -typedef struct credential_set_t credential_set_t; - -/** - * A set of credentials. - * - * Contains private keys, shared keys and different kinds of certificates. - * Enumerators are used because queries might return multiple matches. - * Filter parameters restrict enumeration over specific items only. - * See credential_manager_t for an overview of the credential framework. - * - * A credential set enumerator may not block the credential set, i.e. multiple - * threads must be able to hold multiple enumerators, as the credential manager - * is higly parallelized. The best way to achieve this is by using shared - * read locks for the enumerators only. Otherwiese deadlocks will occur. - * The writing cache_cert() routine is called by the manager only if no - * enumerator is alive, so it is save to use a write lock there. - */ -struct credential_set_t { - - /** - * Create an enumerator over private keys (private_key_t). - * - * The id is either a key identifier of the requested key, or an identity - * of the key owner. - * - * @param type type of requested private key - * @param id key identifier/owner - * @return enumerator over private_key_t's. - */ - enumerator_t *(*create_private_enumerator)(credential_set_t *this, - key_type_t type, identification_t *id); - /** - * Create an enumerator over certificates (certificate_t). - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id identity (subject) this certificate belongs to - * @param trusted whether the certificate must be trustworthy - * @return enumerator as described above - */ - enumerator_t *(*create_cert_enumerator)(credential_set_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Create an enumerator over shared keys (shared_key_t). - * - * The enumerator enumerates over: - * shared_key_t*, id_match_t me, id_match_t other - * But must accept NULL values for the id_matches. - * - * @param type kind of requested shared key - * @param me own identity - * @param other other identity who owns that secret - * @return enumerator as described above - */ - enumerator_t *(*create_shared_enumerator)(credential_set_t *this, - shared_key_type_t type, - identification_t *me, identification_t *other); - - /** - * Create an enumerator over certificate distribution points. - * - * @param type type of the certificate to get a CDP - * @param id identification of the distributed certificate - * @return an enumerator over CDPs as char* - */ - enumerator_t *(*create_cdp_enumerator)(credential_set_t *this, - certificate_type_t type, identification_t *id); - - /** - * Cache a certificate in the credential set. - * - * The caching policy is implementation dependent, the sets may cache the - * certificate in-memory, persistent on disk or not at all. - * - * @param cert certificate to cache - */ - void (*cache_cert)(credential_set_t *this, certificate_t *cert); -}; - -#endif /** CREDENTIAL_SET_H_ @}*/ diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.c b/src/libcharon/credentials/sets/auth_cfg_wrapper.c deleted file mode 100644 index 82e33d283..000000000 --- a/src/libcharon/credentials/sets/auth_cfg_wrapper.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2008-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner - * 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 <daemon.h> - -#include "auth_cfg_wrapper.h" - -typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t; - -/** - * private data of auth_cfg_wrapper - */ -struct private_auth_cfg_wrapper_t { - - /** - * public functions - */ - auth_cfg_wrapper_t public; - - /** - * wrapped auth info - */ - auth_cfg_t *auth; -}; - -/** - * enumerator for auth_cfg_wrapper_t.create_cert_enumerator() - */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** inner enumerator from auth_cfg */ - enumerator_t *inner; - /** wrapped auth round */ - auth_cfg_t *auth; - /** enumerated cert type */ - certificate_type_t cert; - /** enumerated key type */ - key_type_t key; - /** enumerated id */ - identification_t *id; -} wrapper_enumerator_t; - -/** - * Tries to fetch a certificate that was supplied as "Hash and URL" - * (replaces rule type and value in place). - */ -static bool fetch_cert(wrapper_enumerator_t *enumerator, - auth_rule_t *rule, void **value) -{ - char *url = (char*)*value; - if (!url) - { - /* fetching the certificate previously failed */ - return FALSE; - } - - chunk_t data; - certificate_t *cert; - - DBG1(DBG_CFG, " fetching certificate from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, " fetching certificate failed"); - /* we set the item to NULL, so we can skip it */ - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, NULL); - return FALSE; - } - - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, data, BUILD_END); - free(data.ptr); - - if (!cert) - { - DBG1(DBG_CFG, " parsing fetched certificate failed"); - /* we set the item to NULL, so we can skip it */ - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, NULL); - return FALSE; - } - - DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert)); - charon->credentials->cache_cert(charon->credentials, cert); - - if (*rule == AUTH_HELPER_IM_HASH_URL) - { - *rule = AUTH_HELPER_IM_CERT; - } - else - { - *rule = AUTH_HELPER_SUBJECT_CERT; - } - *value = cert; - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, cert->get_ref(cert)); - return TRUE; -} - -/** - * enumerate function for wrapper_enumerator_t - */ -static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) -{ - auth_rule_t rule; - certificate_t *current; - public_key_t *public; - - while (this->inner->enumerate(this->inner, &rule, ¤t)) - { - if (rule == AUTH_HELPER_IM_HASH_URL || - rule == AUTH_HELPER_SUBJECT_HASH_URL) - { /* on-demand fetching of hash and url certificates */ - if (!fetch_cert(this, &rule, (void**)¤t)) - { - continue; - } - } - else if (rule != AUTH_HELPER_SUBJECT_CERT && - rule != AUTH_HELPER_IM_CERT) - { /* handle only HELPER certificates */ - continue; - } - if (this->cert != CERT_ANY && this->cert != current->get_type(current)) - { /* CERT type requested, but does not match */ - continue; - } - public = current->get_public_key(current); - if (this->key != KEY_ANY && !public) - { /* key type requested, but no public key */ - DESTROY_IF(public); - continue; - } - if (this->key != KEY_ANY && public && this->key != public->get_type(public)) - { /* key type requested, but public key has another type */ - DESTROY_IF(public); - continue; - } - DESTROY_IF(public); - if (this->id && !current->has_subject(current, this->id)) - { /* subject requested, but does not match */ - continue; - } - *cert = current; - return TRUE; - } - return FALSE; -} - -/** - * destroy function for wrapper_enumerator_t - */ -static void wrapper_enumerator_destroy(wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - wrapper_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - enumerator = malloc_thing(wrapper_enumerator_t); - enumerator->auth = this->auth; - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->inner = this->auth->create_enumerator(this->auth); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)wrapper_enumerator_destroy; - return &enumerator->public; -} - -/** - * Implementation of auth_cfg_wrapper_t.destroy - */ -static void destroy(private_auth_cfg_wrapper_t *this) -{ - free(this); -} - -/* - * see header file - */ -auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth) -{ - private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_wrapper_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy; - - this->auth = auth; - - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.h b/src/libcharon/credentials/sets/auth_cfg_wrapper.h deleted file mode 100644 index 7653fcdbf..000000000 --- a/src/libcharon/credentials/sets/auth_cfg_wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 auth_cfg_wrapper auth_cfg_wrapper - * @{ @ingroup sets - */ - -#ifndef AUTH_CFG_WRAPPER_H_ -#define AUTH_CFG_WRAPPER_H_ - -#include <config/auth_cfg.h> -#include <credentials/credential_set.h> - -typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t; - -/** - * A wrapper around auth_cfg_t to handle it as a credential set. - */ -struct auth_cfg_wrapper_t { - - /** - * implements credential_set_t - */ - credential_set_t set; - - /** - * Destroy a auth_cfg_wrapper instance. - */ - void (*destroy)(auth_cfg_wrapper_t *this); -}; - -/** - * Create a auth_cfg_wrapper instance. - * - * @param auth the wrapped auth info - * @return wrapper around auth - */ -auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth); - -#endif /** AUTH_CFG_WRAPPER_H_ @}*/ diff --git a/src/libcharon/credentials/sets/cert_cache.c b/src/libcharon/credentials/sets/cert_cache.c deleted file mode 100644 index 176accce2..000000000 --- a/src/libcharon/credentials/sets/cert_cache.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "cert_cache.h" - -#include <time.h> -#include <sched.h> - -#include <daemon.h> -#include <threading/rwlock.h> -#include <utils/linked_list.h> - -/** cache size, a power of 2 for fast modulo */ -#define CACHE_SIZE 32 - -/** attempts to acquire a cache lock */ -#define REPLACE_TRIES 5 - -typedef struct private_cert_cache_t private_cert_cache_t; -typedef struct relation_t relation_t; - -/** - * A trusted relation between subject and issuer - */ -struct relation_t { - - /** - * subject of this relation - */ - certificate_t *subject; - - /** - * issuer of this relation - */ - certificate_t *issuer; - - /** - * Cache hits - */ - u_int hits; - - /** - * Lock for this relation - */ - rwlock_t *lock; -}; - -/** - * private data of cert_cache - */ -struct private_cert_cache_t { - - /** - * public functions - */ - cert_cache_t public; - - /** - * array of trusted subject-issuer relations - */ - relation_t relations[CACHE_SIZE]; -}; - -/** - * Cache relation in a free slot/replace an other - */ -static void cache(private_cert_cache_t *this, - certificate_t *subject, certificate_t *issuer) -{ - relation_t *rel; - int i, offset, try; - u_int total_hits = 0; - - /* check for a unused relation slot first */ - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - - if (!rel->subject && rel->lock->try_write_lock(rel->lock)) - { - /* double-check having lock */ - if (!rel->subject) - { - rel->subject = subject->get_ref(subject); - rel->issuer = issuer->get_ref(issuer); - return rel->lock->unlock(rel->lock); - } - rel->lock->unlock(rel->lock); - } - total_hits += rel->hits; - } - /* run several attempts to replace a random slot, never block. */ - for (try = 0; try < REPLACE_TRIES; try++) - { - /* replace a random relation */ - offset = random(); - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[(i + offset) % CACHE_SIZE]; - - if (rel->hits > total_hits / CACHE_SIZE) - { /* skip often used slots */ - continue; - } - if (rel->lock->try_write_lock(rel->lock)) - { - if (rel->subject) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - } - rel->subject = subject->get_ref(subject); - rel->issuer = issuer->get_ref(issuer); - rel->hits = 0; - return rel->lock->unlock(rel->lock); - } - } - /* give other threads a chance to release locks */ - sched_yield(); - } -} - -/** - * Implementation of cert_cache_t.issued_by. - */ -static bool issued_by(private_cert_cache_t *this, - certificate_t *subject, certificate_t *issuer) -{ - relation_t *found = NULL, *current; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - current = &this->relations[i]; - - current->lock->read_lock(current->lock); - if (current->subject) - { - /* check for equal issuer */ - if (issuer->equals(issuer, current->issuer)) - { - /* reuse issuer instance in cache() */ - issuer = current->issuer; - if (subject->equals(subject, current->subject)) - { - /* write hit counter is not locked, but not critical */ - current->hits++; - found = current; - } - } - } - current->lock->unlock(current->lock); - if (found) - { - return TRUE; - } - } - /* no cache hit, check and cache signature */ - if (subject->issued_by(subject, issuer)) - { - cache(this, subject, issuer); - return TRUE; - } - return FALSE; -} - -/** - * certificate enumerator implemenation - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** type of requested certificate */ - certificate_type_t cert; - /** type of requested key */ - key_type_t key; - /** ID to get a cert for */ - identification_t *id; - /** cache */ - relation_t *relations; - /** current position in array cache */ - int index; - /** currently locked relation */ - int locked; -} cert_enumerator_t; - -/** - * filter function for certs enumerator - */ -static bool cert_enumerate(cert_enumerator_t *this, certificate_t **out) -{ - public_key_t *public; - relation_t *rel; - - if (this->locked >= 0) - { - rel = &this->relations[this->locked]; - rel->lock->unlock(rel->lock); - this->locked = -1; - } - - while (++this->index < CACHE_SIZE) - { - rel = &this->relations[this->index]; - rel->lock->read_lock(rel->lock); - this->locked = this->index; - if (rel->subject) - { - /* CRL lookup is done using issuer/authkeyidentifier */ - if (this->key == KEY_ANY && this->id && - (this->cert == CERT_ANY || this->cert == CERT_X509_CRL) && - rel->subject->get_type(rel->subject) == CERT_X509_CRL && - rel->subject->has_issuer(rel->subject, this->id)) - { - *out = rel->subject; - return TRUE; - } - if ((this->cert == CERT_ANY || - rel->subject->get_type(rel->subject) == this->cert) && - (!this->id || rel->subject->has_subject(rel->subject, this->id))) - { - if (this->key == KEY_ANY) - { - *out = rel->subject; - return TRUE; - } - public = rel->subject->get_public_key(rel->subject); - if (public) - { - if (public->get_type(public) == this->key) - { - public->destroy(public); - *out = rel->subject; - return TRUE; - } - public->destroy(public); - } - } - } - this->locked = -1; - rel->lock->unlock(rel->lock); - } - return FALSE; -} - -/** - * clean up enumeration data - */ -static void cert_enumerator_destroy(cert_enumerator_t *this) -{ - relation_t *rel; - - if (this->locked >= 0) - { - rel = &this->relations[this->locked]; - rel->lock->unlock(rel->lock); - } - free(this); -} - -/** - * implementation of credential_set_t.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_cert_cache_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - cert_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - enumerator = malloc_thing(cert_enumerator_t); - enumerator->public.enumerate = (void*)cert_enumerate; - enumerator->public.destroy = (void*)cert_enumerator_destroy; - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->relations = this->relations; - enumerator->index = -1; - enumerator->locked = -1; - - return &enumerator->public; -} - -/** - * Implementation of cert_cache_t.flush. - */ -static void flush(private_cert_cache_t *this, certificate_type_t type) -{ - relation_t *rel; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - if (!rel->subject) - { - continue; - } - /* check with cheap read lock first */ - if (type != CERT_ANY) - { - rel->lock->read_lock(rel->lock); - if (!rel->subject || type != rel->subject->get_type(rel->subject)) - { - rel->lock->unlock(rel->lock); - continue; - } - rel->lock->unlock(rel->lock); - } - /* double check in write lock */ - rel->lock->write_lock(rel->lock); - if (rel->subject) - { - if (type == CERT_ANY || type == rel->subject->get_type(rel->subject)) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - rel->subject = NULL; - rel->issuer = NULL; - rel->hits = 0; - } - } - rel->lock->unlock(rel->lock); - } -} - -/** - * Implementation of cert_cache_t.destroy - */ -static void destroy(private_cert_cache_t *this) -{ - relation_t *rel; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - if (rel->subject) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - } - rel->lock->destroy(rel->lock); - } - free(this); -} - -/* - * see header file - */ -cert_cache_t *cert_cache_create() -{ - private_cert_cache_t *this; - int i; - - this = malloc_thing(private_cert_cache_t); - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by; - this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush; - this->public.destroy = (void(*)(cert_cache_t*))destroy; - - for (i = 0; i < CACHE_SIZE; i++) - { - this->relations[i].subject = NULL; - this->relations[i].issuer = NULL; - this->relations[i].hits = 0; - this->relations[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - } - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/cert_cache.h b/src/libcharon/credentials/sets/cert_cache.h deleted file mode 100644 index d2721866e..000000000 --- a/src/libcharon/credentials/sets/cert_cache.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 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 cert_cache cert_cache - * @{ @ingroup sets - */ - -#ifndef CERT_CACHE_H_ -#define CERT_CACHE_H_ - -#include <credentials/credential_set.h> - -typedef struct cert_cache_t cert_cache_t; - -/** - * Certificate signature verification and certificate cache. - * - * This cache serves all certificates seen in its issued_by method - * and serves them as untrusted through the credential set interface. Further, - * it caches valid subject-issuer relationships to speed up the issued_by - * method. - */ -struct cert_cache_t { - - /** - * Implements credential_set_t. - */ - credential_set_t set; - - /** - * Caching wrapper around certificate_t.issued_by. - * - * @param subject certificate to verify - * @param issuer issuing certificate to verify subject - * @return TRUE if subject issued by issuer - */ - bool (*issued_by)(cert_cache_t *this, - certificate_t *subject, certificate_t *issuer); - - /** - * Flush the certificate cache. - * - * @param type type of certificate to flush, or CERT_ANY - */ - void (*flush)(cert_cache_t *this, certificate_type_t type); - - /** - * Destroy a cert_cache instance. - */ - void (*destroy)(cert_cache_t *this); -}; - -/** - * Create a cert_cache instance. - */ -cert_cache_t *cert_cache_create(); - -#endif /** CERT_CACHE_H_ @}*/ diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.c b/src/libcharon/credentials/sets/ocsp_response_wrapper.c deleted file mode 100644 index 82079209a..000000000 --- a/src/libcharon/credentials/sets/ocsp_response_wrapper.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "ocsp_response_wrapper.h" - -typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t; - -/** - * private data of ocsp_response_wrapper - */ -struct private_ocsp_response_wrapper_t { - - /** - * public functions - */ - ocsp_response_wrapper_t public; - - /** - * wrapped OCSP response - */ - ocsp_response_t *response; -}; - -/** - * enumerator for ocsp_response_wrapper_t.create_cert_enumerator() - */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** enumerator over ocsp response */ - enumerator_t *inner; - /** type of cert */ - certificate_type_t cert; - /** type of key */ - key_type_t key; - /** filtering identity */ - identification_t *id; -} wrapper_enumerator_t; - -/** - * enumerate function wrapper_enumerator_t - */ -static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) -{ - certificate_t *current; - public_key_t *public; - - while (this->inner->enumerate(this->inner, ¤t)) - { - if (this->cert != CERT_ANY && this->cert != current->get_type(current)) - { /* CERT type requested, but does not match */ - continue; - } - public = current->get_public_key(current); - if (this->key != KEY_ANY && !public) - { /* key type requested, but no public key */ - DESTROY_IF(public); - continue; - } - if (this->key != KEY_ANY && public && this->key != public->get_type(public)) - { /* key type requested, but public key has another type */ - DESTROY_IF(public); - continue; - } - DESTROY_IF(public); - if (this->id && !current->has_subject(current, this->id)) - { /* subject requested, but does not match */ - continue; - } - *cert = current; - return TRUE; - } - return FALSE; -} - -/** - * destroy function for wrapper_enumerator_t - */ -static void enumerator_destroy(wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - wrapper_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - - enumerator = malloc_thing(wrapper_enumerator_t); - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->inner = this->response->create_cert_enumerator(this->response); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)enumerator_destroy; - return &enumerator->public; -} - -/** - * Implementation of ocsp_response_wrapper_t.destroy - */ -static void destroy(private_ocsp_response_wrapper_t *this) -{ - free(this); -} - -/* - * see header file - */ -ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response) -{ - private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy; - - this->response = response; - - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.h b/src/libcharon/credentials/sets/ocsp_response_wrapper.h deleted file mode 100644 index dc4b451df..000000000 --- a/src/libcharon/credentials/sets/ocsp_response_wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 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 ocsp_response_wrapper ocsp_response_wrapper - * @{ @ingroup sets - */ - -#ifndef OCSP_RESPONSE_WRAPPER_H_ -#define OCSP_RESPONSE_WRAPPER_H_ - -#include <credentials/credential_set.h> -#include <credentials/certificates/ocsp_response.h> - -typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t; - -/** - * A wrapper around ocsp_response_t to handle it like a credential set. - */ -struct ocsp_response_wrapper_t { - - /** - * implements credential_set_t - */ - credential_set_t set; - - /** - * Destroy a ocsp_response_wrapper instance. - */ - void (*destroy)(ocsp_response_wrapper_t *this); -}; - -/** - * Create a ocsp_response_wrapper instance. - * - * @param response the wrapped OCSP response - * @return wrapper around response - */ -ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response); - -#endif /** OCSP_RESPONSE_WRAPPER_H_ @}*/ diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index 11c94beb9..c0227027c 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -19,16 +19,19 @@ #include <stdio.h> #include <sys/types.h> #include <unistd.h> +#include <syslog.h> #include <time.h> #include <errno.h> + #ifdef CAPABILITIES +#ifdef HAVE_SYS_CAPABILITY_H #include <sys/capability.h> +#endif /* HAVE_SYS_CAPABILITY_H */ #endif /* CAPABILITIES */ #include "daemon.h" #include <library.h> -#include <selectors/traffic_selector.h> #include <config/proposal.h> #ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */ @@ -46,12 +49,16 @@ struct private_daemon_t { */ daemon_t public; -#ifdef CAPABILITIES /** * capabilities to keep */ +#ifdef CAPABILITIES_LIBCAP cap_t caps; -#endif /* CAPABILITIES */ +#endif /* CAPABILITIES_LIBCAP */ +#ifdef CAPABILITIES_NATIVE + struct __user_cap_data_struct caps; +#endif /* CAPABILITIES_NATIVE */ + }; /** @@ -97,11 +104,12 @@ static void destroy(private_daemon_t *this) this->public.ike_sa_manager->flush(this->public.ike_sa_manager); } DESTROY_IF(this->public.receiver); + DESTROY_IF(this->public.sender); /* unload plugins to release threads */ lib->plugins->unload(lib->plugins); -#ifdef CAPABILITIES +#ifdef CAPABILITIES_LIBCAP cap_free(this->caps); -#endif /* CAPABILITIES */ +#endif /* CAPABILITIES_LIBCAP */ DESTROY_IF(this->public.traps); DESTROY_IF(this->public.ike_sa_manager); DESTROY_IF(this->public.kernel_interface); @@ -114,8 +122,6 @@ static void destroy(private_daemon_t *this) DESTROY_IF(this->public.mediation_manager); #endif /* ME */ DESTROY_IF(this->public.backends); - DESTROY_IF(this->public.credentials); - DESTROY_IF(this->public.sender); DESTROY_IF(this->public.socket); /* wait until all threads are gone */ DESTROY_IF(this->public.processor); @@ -133,22 +139,36 @@ static void destroy(private_daemon_t *this) METHOD(daemon_t, keep_cap, void, private_daemon_t *this, u_int cap) { -#ifdef CAPABILITIES +#ifdef CAPABILITIES_LIBCAP cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET); cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET); cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET); -#endif /* CAPABILITIES */ +#endif /* CAPABILITIES_LIBCAP */ +#ifdef CAPABILITIES_NATIVE + this->caps.effective |= 1 << cap; + this->caps.permitted |= 1 << cap; + this->caps.inheritable |= 1 << cap; +#endif /* CAPABILITIES_NATIVE */ } METHOD(daemon_t, drop_capabilities, bool, private_daemon_t *this) { -#ifdef CAPABILITIES +#ifdef CAPABILITIES_LIBCAP if (cap_set_proc(this->caps) != 0) { return FALSE; } -#endif /* CAPABILITIES */ +#endif /* CAPABILITIES_LIBCAP */ +#ifdef CAPABILITIES_NATIVE + struct __user_cap_header_struct header = { + .version = _LINUX_CAPABILITY_VERSION, + }; + if (capset(&header, &this->caps) != 0) + { + return FALSE; + } +#endif /* CAPABILITIES_NATIVE */ return TRUE; } @@ -254,8 +274,15 @@ static void initialize_loggers(private_daemon_t *this, bool use_stderr, filename, strerror(errno)); continue; } + if (lib->settings->get_bool(lib->settings, + "charon.filelog.%s.flush_line", FALSE, filename)) + { + setlinebuf(file); + } } - file_logger = file_logger_create(file); + file_logger = file_logger_create(file, + lib->settings->get_str(lib->settings, + "charon.filelog.%s.time_format", NULL, filename)); def = lib->settings->get_int(lib->settings, "charon.filelog.%s.default", 1, filename); for (group = 0; group < DBG_MAX; group++) @@ -276,7 +303,7 @@ static void initialize_loggers(private_daemon_t *this, bool use_stderr, if (!loggers_defined) { /* set up default stdout file_logger */ - file_logger = file_logger_create(stdout); + file_logger = file_logger_create(stdout, NULL); this->public.bus->add_listener(this->public.bus, &file_logger->listener); this->public.file_loggers->insert_last(this->public.file_loggers, file_logger); @@ -331,7 +358,6 @@ METHOD(daemon_t, initialize, bool, /* load secrets, ca certificates and crls */ this->public.processor = processor_create(); this->public.scheduler = scheduler_create(); - this->public.credentials = credential_manager_create(); this->public.controller = controller_create(); this->public.eap = eap_manager_create(); this->public.sim = sim_manager_create(); @@ -392,7 +418,9 @@ private_daemon_t *daemon_create() ); #ifdef CAPABILITIES +#ifdef CAPABILITIES_LIBCAP this->caps = cap_init(); +#endif /* CAPABILITIES_LIBCAP */ keep_cap(this, CAP_NET_ADMIN); if (lib->leak_detective) { @@ -423,10 +451,6 @@ bool libcharon_init() this = daemon_create(); charon = &this->public; - lib->printf_hook->add_handler(lib->printf_hook, 'R', - traffic_selector_printf_hook, - PRINTF_HOOK_ARGTYPE_POINTER, - PRINTF_HOOK_ARGTYPE_END); lib->printf_hook->add_handler(lib->printf_hook, 'P', proposal_printf_hook, PRINTF_HOOK_ARGTYPE_POINTER, diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h index 9b6d97060..38f0256e7 100644 --- a/src/libcharon/daemon.h +++ b/src/libcharon/daemon.h @@ -31,12 +31,6 @@ * @defgroup control control * @ingroup libcharon * - * @defgroup ccredentials credentials - * @ingroup libcharon - * - * @defgroup sets sets - * @ingroup ccredentials - * * @defgroup encoding encoding * @ingroup libcharon * @@ -156,7 +150,6 @@ typedef struct daemon_t daemon_t; #include <sa/ike_sa_manager.h> #include <sa/trap_manager.h> #include <config/backend_manager.h> -#include <credentials/credential_manager.h> #include <sa/authenticators/eap/eap_manager.h> #include <sa/authenticators/eap/sim_manager.h> @@ -206,11 +199,6 @@ struct daemon_t { backend_manager_t *backends; /** - * Manager for the credential backends - */ - credential_manager_t *credentials; - - /** * The Sender-Thread. */ sender_t *sender; diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index acfc0fd44..ee49a6686 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -31,6 +31,7 @@ #include <encoding/payloads/payload.h> #include <encoding/payloads/encryption_payload.h> #include <encoding/payloads/unknown_payload.h> +#include <encoding/payloads/cp_payload.h> /** * Max number of notify payloads per IKEv2 Message @@ -975,6 +976,39 @@ static char* get_string(private_message_t *this, char *buf, int len) pos += written; len -= written; } + if (payload->get_type(payload) == CONFIGURATION) + { + cp_payload_t *cp = (cp_payload_t*)payload; + enumerator_t *attributes; + configuration_attribute_t *attribute; + bool first = TRUE; + + attributes = cp->create_attribute_enumerator(cp); + while (attributes->enumerate(attributes, &attribute)) + { + written = snprintf(pos, len, "%s%N", first ? "(" : " ", + configuration_attribute_type_short_names, + attribute->get_type(attribute)); + if (written >= len || written < 0) + { + return buf; + } + pos += written; + len -= written; + first = FALSE; + } + attributes->destroy(attributes); + if (!first) + { + written = snprintf(pos, len, ")"); + if (written >= len || written < 0) + { + return buf; + } + pos += written; + len -= written; + } + } } enumerator->destroy(enumerator); diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c index 6dd3141f0..80239f654 100644 --- a/src/libcharon/encoding/payloads/cert_payload.c +++ b/src/libcharon/encoding/payloads/cert_payload.c @@ -320,7 +320,12 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert) free(this); return NULL; } - this->data = cert->get_encoding(cert); + if (!cert->get_encoding(cert, CERT_ASN1_DER, &this->data)) + { + DBG1(DBG_ENC, "encoding certificate for cert payload failed"); + free(this); + return NULL; + } this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; return &this->public; } diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c index 64a43a7fc..837e628bc 100644 --- a/src/libcharon/kernel/kernel_interface.c +++ b/src/libcharon/kernel/kernel_interface.c @@ -67,8 +67,8 @@ METHOD(kernel_interface_t, get_cpi, status_t, METHOD(kernel_interface_t, add_sa, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, - 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, + mark_t mark, 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) { @@ -77,82 +77,84 @@ METHOD(kernel_interface_t, add_sa, status_t, return NOT_SUPPORTED; } return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid, - lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi, - encap, inbound, src_ts, dst_ts); + mark, lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, + cpi, encap, inbound, src_ts, dst_ts); } METHOD(kernel_interface_t, update_sa, status_t, private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool encap, bool new_encap) + bool encap, bool new_encap, mark_t mark) { if (!this->ipsec) { return NOT_SUPPORTED; } return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst, - new_src, new_dst, encap, new_encap); + new_src, new_dst, encap, new_encap, mark); } METHOD(kernel_interface_t, query_sa, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes) + u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) { if (!this->ipsec) { return NOT_SUPPORTED; } - return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes); + return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark, bytes); } METHOD(kernel_interface_t, del_sa, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, - protocol_id_t protocol, u_int16_t cpi) + protocol_id_t protocol, u_int16_t cpi, mark_t mark) { if (!this->ipsec) { return NOT_SUPPORTED; } - return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi); + return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark); } METHOD(kernel_interface_t, add_policy, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, - u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed) + u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed) { if (!this->ipsec) { return NOT_SUPPORTED; } return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts, - direction, spi, protocol, reqid, mode, ipcomp, cpi, routed); + direction, spi, protocol, reqid, mark, mode, ipcomp, cpi, routed); } METHOD(kernel_interface_t, query_policy, status_t, private_kernel_interface_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { if (!this->ipsec) { return NOT_SUPPORTED; } return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts, - direction, use_time); + direction, mark, use_time); } METHOD(kernel_interface_t, del_policy, status_t, private_kernel_interface_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + bool unrouted) { if (!this->ipsec) { return NOT_SUPPORTED; } return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts, - direction, unrouted); + direction, mark, unrouted); } METHOD(kernel_interface_t, get_source_addr, host_t*, diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h index 4a62e76b8..92d85f9c9 100644 --- a/src/libcharon/kernel/kernel_interface.h +++ b/src/libcharon/kernel/kernel_interface.h @@ -90,6 +90,7 @@ struct kernel_interface_t { * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) * @param reqid unique ID for this SA + * @param mark optional mark for this SA * @param lifetime lifetime_cfg_t for this SA * @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_key key to use for encryption @@ -106,7 +107,7 @@ struct kernel_interface_t { */ status_t (*add_sa) (kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, - protocol_id_t protocol, u_int32_t reqid, + protocol_id_t protocol, u_int32_t reqid, mark_t mark, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, @@ -131,6 +132,7 @@ struct kernel_interface_t { * @param new_dst new destination address * @param encap current use of UDP encapsulation * @param new_encap new use of UDP encapsulation + * @param mark optional mark for this SA * @return SUCCESS if operation completed, NOT_SUPPORTED if * the kernel interface can't update the SA */ @@ -138,7 +140,7 @@ struct kernel_interface_t { u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool encap, bool new_encap); + bool encap, bool new_encap, mark_t mark); /** * Query the number of bytes processed by an SA from the SAD. @@ -147,11 +149,13 @@ struct kernel_interface_t { * @param dst destination address for this SA * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) + * @param mark optional mark for this SA * @param[out] bytes the number of bytes processed by SA * @return SUCCESS if operation completed */ status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes); + u_int32_t spi, protocol_id_t protocol, mark_t mark, + u_int64_t *bytes); /** * Delete a previously installed SA from the SAD. @@ -161,10 +165,12 @@ struct kernel_interface_t { * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) * @param cpi CPI for IPComp or 0 + * @param mark optional mark for this SA * @return SUCCESS if operation completed */ status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi); + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, + mark_t mark); /** * Add a policy to the SPD. @@ -180,6 +186,7 @@ struct kernel_interface_t { * @param spi SPI of SA * @param protocol protocol to use to protect traffic (AH/ESP) * @param reqid unique ID of an SA to use to enforce policy + * @param mark mark for this policy * @param mode mode of SA (tunnel, transport) * @param ipcomp the IPComp transform used * @param cpi CPI for IPComp @@ -192,8 +199,8 @@ struct kernel_interface_t { traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, - ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed); + mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed); /** * Query the use time of a policy. @@ -204,13 +211,15 @@ struct kernel_interface_t { * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD + * @param mark optional mark * @param[out] use_time the time of this SA's last use * @return SUCCESS if operation completed */ status_t (*query_policy) (kernel_interface_t *this, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, - policy_dir_t direction, u_int32_t *use_time); + policy_dir_t direction, mark_t mark, + u_int32_t *use_time); /** * Remove a policy from the SPD. @@ -223,13 +232,14 @@ struct kernel_interface_t { * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD + * @param mark optional mark * @param unrouted TRUE, if this policy is unrouted from the kernel * @return SUCCESS if operation completed */ status_t (*del_policy) (kernel_interface_t *this, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, - policy_dir_t direction, + policy_dir_t direction, mark_t mark, bool unrouted); /** diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h index 300464cf6..d09265cc9 100644 --- a/src/libcharon/kernel/kernel_ipsec.h +++ b/src/libcharon/kernel/kernel_ipsec.h @@ -121,6 +121,7 @@ struct kernel_ipsec_t { * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) * @param reqid unique ID for this SA + * @param mark mark for this SA * @param lifetime lifetime_cfg_t for this SA * @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_key key to use for encryption @@ -138,7 +139,7 @@ struct kernel_ipsec_t { status_t (*add_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, - lifetime_cfg_t *lifetime, + mark_t mark, 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, @@ -162,6 +163,7 @@ struct kernel_ipsec_t { * @param new_dst new destination address * @param encap current use of UDP encapsulation * @param new_encap new use of UDP encapsulation + * @param mark optional mark for this SA * @return SUCCESS if operation completed, NOT_SUPPORTED if * the kernel interface can't update the SA */ @@ -169,7 +171,7 @@ struct kernel_ipsec_t { u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool encap, bool new_encap); + bool encap, bool new_encap, mark_t mark); /** * Query the number of bytes processed by an SA from the SAD. @@ -178,11 +180,13 @@ struct kernel_ipsec_t { * @param dst destination address for this SA * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) + * @param mark optional mark for this SA * @param[out] bytes the number of bytes processed by SA * @return SUCCESS if operation completed */ status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes); + u_int32_t spi, protocol_id_t protocol, mark_t mark, + u_int64_t *bytes); /** * Delete a previusly installed SA from the SAD. @@ -192,10 +196,12 @@ struct kernel_ipsec_t { * @param spi SPI allocated by us or remote peer * @param protocol protocol for this SA (ESP/AH) * @param cpi CPI for IPComp or 0 + * @param mark optional mark for this SA * @return SUCCESS if operation completed */ status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi); + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, + mark_t mark); /** * Add a policy to the SPD. @@ -211,6 +217,7 @@ struct kernel_ipsec_t { * @param spi SPI of SA * @param protocol protocol to use to protect traffic (AH/ESP) * @param reqid unique ID of an SA to use to enforce policy + * @param mark mark for this policy * @param mode mode of SA (tunnel, transport) * @param ipcomp the IPComp transform used * @param cpi CPI for IPComp @@ -223,8 +230,8 @@ struct kernel_ipsec_t { traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, - ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed); + mark_t mark, ipsec_mode_t mode, + u_int16_t ipcomp, u_int16_t cpi, bool routed); /** * Query the use time of a policy. @@ -236,13 +243,15 @@ struct kernel_ipsec_t { * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD + * @param mark optional mark * @param[out] use_time the monotonic timestamp of this SA's last use * @return SUCCESS if operation completed */ status_t (*query_policy) (kernel_ipsec_t *this, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, - policy_dir_t direction, u_int32_t *use_time); + policy_dir_t direction, mark_t mark, + u_int32_t *use_time); /** * Remove a policy from the SPD. @@ -255,13 +264,14 @@ struct kernel_ipsec_t { * @param src_ts traffic selector to match traffic source * @param dst_ts traffic selector to match traffic dest * @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD + * @param mark optional mark * @param unrouted TRUE, if this policy is unrouted from the kernel * @return SUCCESS if operation completed */ status_t (*del_policy) (kernel_ipsec_t *this, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, - policy_dir_t direction, + policy_dir_t direction, mark_t mark, bool unrouted); /** diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c index df897021a..63a8cab58 100644 --- a/src/libcharon/network/receiver.c +++ b/src/libcharon/network/receiver.c @@ -103,7 +103,22 @@ struct private_receiver_t { /** * Delay for receiving incoming packets, to simulate larger RTT */ - u_int receive_delay; + int receive_delay; + + /** + * Specific message type to delay, 0 for any + */ + int receive_delay_type; + + /** + * Delay request messages? + */ + bool receive_delay_request; + + /** + * Delay response messages? + */ + bool receive_delay_response; }; /** @@ -242,7 +257,7 @@ static bool cookie_required(private_receiver_t *this, message_t *message) /** * check if peer has to many half open IKE_SAs */ -static bool peer_to_aggressive(private_receiver_t *this, message_t *message) +static bool peer_too_aggressive(private_receiver_t *this, message_t *message) { if (charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager, message->get_source(message)) >= this->block_threshold) @@ -259,7 +274,6 @@ static job_requeue_t receive_packets(private_receiver_t *this) { packet_t *packet; message_t *message; - job_t *job; /* read in a packet */ if (charon->socket->receive(charon->socket, &packet) != SUCCESS) @@ -321,7 +335,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) } /* check if peer has not too many IKE_SAs half open */ - if (this->block_threshold && peer_to_aggressive(this, message)) + if (this->block_threshold && peer_too_aggressive(this, message)) { DBG1(DBG_NET, "ignoring IKE_SA setup from %H, " "peer too aggressive", message->get_source(message)); @@ -329,16 +343,25 @@ static job_requeue_t receive_packets(private_receiver_t *this) return JOB_REQUEUE_DIRECT; } } - job = (job_t*)process_message_job_create(message); if (this->receive_delay) { - charon->scheduler->schedule_job_ms(charon->scheduler, - job, this->receive_delay); - } - else - { - charon->processor->queue_job(charon->processor, job); + if (this->receive_delay_type == 0 || + this->receive_delay_type == message->get_exchange_type(message)) + { + if ((message->get_request(message) && this->receive_delay_request) || + (!message->get_request(message) && this->receive_delay_response)) + { + DBG1(DBG_NET, "using receive delay: %dms", + this->receive_delay); + charon->scheduler->schedule_job_ms(charon->scheduler, + (job_t*)process_message_job_create(message), + this->receive_delay); + return JOB_REQUEUE_DIRECT; + } + } } + charon->processor->queue_job(charon->processor, + (job_t*)process_message_job_create(message)); return JOB_REQUEUE_DIRECT; } @@ -374,6 +397,12 @@ receiver_t *receiver_create() } this->receive_delay = lib->settings->get_int(lib->settings, "charon.receive_delay", 0); + this->receive_delay_type = lib->settings->get_int(lib->settings, + "charon.receive_delay_type", 0), + this->receive_delay_request = lib->settings->get_bool(lib->settings, + "charon.receive_delay_request", TRUE), + this->receive_delay_response = lib->settings->get_int(lib->settings, + "charon.receive_delay_response", TRUE), this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED); if (this->hasher == NULL) diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c index c18f1138e..bb6d50605 100644 --- a/src/libcharon/network/sender.c +++ b/src/libcharon/network/sender.c @@ -67,6 +67,21 @@ struct private_sender_t { * Delay for sending outgoing packets, to simulate larger RTT */ int send_delay; + + /** + * Specific message type to delay, 0 for any + */ + int send_delay_type; + + /** + * Delay request messages? + */ + bool send_delay_request; + + /** + * Delay response messages? + */ + bool send_delay_response; }; METHOD(sender_t, send_, void, @@ -80,7 +95,23 @@ METHOD(sender_t, send_, void, if (this->send_delay) { - usleep(this->send_delay * 1000); + message_t *message; + + message = message_create_from_packet(packet->clone(packet)); + if (message->parse_header(message) == SUCCESS) + { + if (this->send_delay_type == 0 || + this->send_delay_type == message->get_exchange_type(message)) + { + if ((message->get_request(message) && this->send_delay_request) || + (!message->get_request(message) && this->send_delay_response)) + { + DBG1(DBG_NET, "using send delay: %dms", this->send_delay); + usleep(this->send_delay * 1000); + } + } + } + message->destroy(message); } this->mutex->lock(this->mutex); @@ -155,7 +186,13 @@ sender_t * sender_create() .job = callback_job_create((callback_job_cb_t)send_packets, this, NULL, NULL), .send_delay = lib->settings->get_int(lib->settings, - "charon.send_delay", 0), + "charon.send_delay", 0), + .send_delay_type = lib->settings->get_int(lib->settings, + "charon.send_delay_type", 0), + .send_delay_request = lib->settings->get_bool(lib->settings, + "charon.send_delay_request", TRUE), + .send_delay_response = lib->settings->get_int(lib->settings, + "charon.send_delay_response", TRUE), ); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am new file mode 100644 index 000000000..50d0457f8 --- /dev/null +++ b/src/libcharon/plugins/addrblock/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 + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-addrblock.la +else +plugin_LTLIBRARIES = libstrongswan-addrblock.la +endif + +libstrongswan_addrblock_la_SOURCES = \ + addrblock_plugin.h addrblock_plugin.c \ + addrblock_narrow.h addrblock_narrow.c \ + addrblock_validator.h addrblock_validator.c + +libstrongswan_addrblock_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index 92ee85539..4cb047929 100644 --- a/src/libcharon/plugins/resolve/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -34,7 +34,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -subdir = src/libcharon/plugins/resolve +subdir = src/libcharon/plugins/addrblock DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ @@ -73,17 +73,18 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_resolve_la_LIBADD = -am_libstrongswan_resolve_la_OBJECTS = resolve_plugin.lo \ - resolve_handler.lo -libstrongswan_resolve_la_OBJECTS = \ - $(am_libstrongswan_resolve_la_OBJECTS) -libstrongswan_resolve_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libstrongswan_resolve_la_LDFLAGS) $(LDFLAGS) -o $@ -@MONOLITHIC_FALSE@am_libstrongswan_resolve_la_rpath = -rpath \ +libstrongswan_addrblock_la_LIBADD = +am_libstrongswan_addrblock_la_OBJECTS = addrblock_plugin.lo \ + addrblock_narrow.lo addrblock_validator.lo +libstrongswan_addrblock_la_OBJECTS = \ + $(am_libstrongswan_addrblock_la_OBJECTS) +libstrongswan_addrblock_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_addrblock_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_addrblock_la_rpath = -rpath \ @MONOLITHIC_FALSE@ $(plugindir) -@MONOLITHIC_TRUE@am_libstrongswan_resolve_la_rpath = +@MONOLITHIC_TRUE@am_libstrongswan_addrblock_la_rpath = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -97,8 +98,8 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libstrongswan_resolve_la_SOURCES) -DIST_SOURCES = $(libstrongswan_resolve_la_SOURCES) +SOURCES = $(libstrongswan_addrblock_la_SOURCES) +DIST_SOURCES = $(libstrongswan_addrblock_la_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -260,16 +261,15 @@ xml_LIBS = @xml_LIBS@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon -AM_CFLAGS = -rdynamic \ - -DRESOLV_CONF=\"${resolv_conf}\" - -@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-resolve.la -@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-resolve.la -libstrongswan_resolve_la_SOURCES = \ - resolve_plugin.h resolve_plugin.c \ - resolve_handler.h resolve_handler.c +AM_CFLAGS = -rdynamic +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-addrblock.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-addrblock.la +libstrongswan_addrblock_la_SOURCES = \ + addrblock_plugin.h addrblock_plugin.c \ + addrblock_narrow.h addrblock_narrow.c \ + addrblock_validator.h addrblock_validator.c -libstrongswan_resolve_la_LDFLAGS = -module -avoid-version +libstrongswan_addrblock_la_LDFLAGS = -module -avoid-version all: all-am .SUFFIXES: @@ -283,9 +283,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/addrblock/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/Makefile + $(AUTOMAKE) --gnu src/libcharon/plugins/addrblock/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -344,8 +344,8 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libstrongswan-resolve.la: $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_DEPENDENCIES) - $(libstrongswan_resolve_la_LINK) $(am_libstrongswan_resolve_la_rpath) $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_LIBADD) $(LIBS) +libstrongswan-addrblock.la: $(libstrongswan_addrblock_la_OBJECTS) $(libstrongswan_addrblock_la_DEPENDENCIES) + $(libstrongswan_addrblock_la_LINK) $(am_libstrongswan_addrblock_la_rpath) $(libstrongswan_addrblock_la_OBJECTS) $(libstrongswan_addrblock_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -353,8 +353,9 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_handler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_narrow.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_validator.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.c b/src/libcharon/plugins/addrblock/addrblock_narrow.c new file mode 100644 index 000000000..f85fa78d6 --- /dev/null +++ b/src/libcharon/plugins/addrblock/addrblock_narrow.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * Copyright (C) 2009 Andreas Steffen + * 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 "addrblock_narrow.h" + +#include <daemon.h> +#include <credentials/certificates/x509.h> + +typedef struct private_addrblock_narrow_t private_addrblock_narrow_t; + +/** + * Private data of an addrblock_narrow_t object. + */ +struct private_addrblock_narrow_t { + + /** + * Public addrblock_narrow_t interface. + */ + addrblock_narrow_t public; +}; + +/** + * Check if the negotiated TS list is acceptable by X509 ipAddrBlock constraints + */ +static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list) +{ + auth_cfg_t *auth; + enumerator_t *auth_enum; + certificate_t *cert = NULL; + + auth_enum = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE); + while (auth_enum->enumerate(auth_enum, &auth)) + { + cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT); + if (cert) + { + break; + } + } + auth_enum->destroy(auth_enum); + + if (cert && cert->get_type(cert) == CERT_X509) + { + x509_t *x509 = (x509_t*)cert; + + if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS) + { + enumerator_t *enumerator, *block_enum; + traffic_selector_t *ts, *block_ts; + + DBG1(DBG_IKE, "checking certificate-based traffic selector " + "constraints [RFC 3779]"); + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &ts)) + { + bool contained = FALSE; + + block_enum = x509->create_ipAddrBlock_enumerator(x509); + while (block_enum->enumerate(block_enum, &block_ts)) + { + if (ts->is_contained_in(ts, block_ts)) + { + DBG1(DBG_IKE, " TS %R is contained in address block" + " constraint %R", ts, block_ts); + contained = TRUE; + break; + } + } + block_enum->destroy(block_enum); + + if (!contained) + { + DBG1(DBG_IKE, " TS %R is not contained in any" + " address block constraint", ts); + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + } + } + return TRUE; +} + +/** + * Delete all traffic selectors in a list + */ +static void flush_ts_list(linked_list_t *list) +{ + traffic_selector_t *ts; + + while (list->remove_last(list, (void**)&ts) == SUCCESS) + { + ts->destroy(ts); + } +} + +METHOD(listener_t, narrow, bool, + private_addrblock_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + narrow_hook_t type, linked_list_t *local, linked_list_t *remote) +{ + switch (type) + { + case NARROW_RESPONDER: + case NARROW_INITIATOR_POST_AUTH: + case NARROW_INITIATOR_POST_NOAUTH: + if (!check_constraints(ike_sa, remote)) + { + flush_ts_list(local); + flush_ts_list(remote); + } + break; + default: + break; + } + return TRUE; +} + +METHOD(addrblock_narrow_t, destroy, void, + private_addrblock_narrow_t *this) +{ + free(this); +} + +/** + * See header + */ +addrblock_narrow_t *addrblock_narrow_create() +{ + private_addrblock_narrow_t *this; + + INIT(this, + .public = { + .listener.narrow = _narrow, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.h b/src/libcharon/plugins/addrblock/addrblock_narrow.h new file mode 100644 index 000000000..9ab32e671 --- /dev/null +++ b/src/libcharon/plugins/addrblock/addrblock_narrow.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup addrblock_narrow addrblock_narrow + * @{ @ingroup addrblock + */ + +#ifndef ADDRBLOCK_NARROW_H_ +#define ADDRBLOCK_NARROW_H_ + +#include <bus/listeners/listener.h> + +typedef struct addrblock_narrow_t addrblock_narrow_t; + +/** + * Listener that checks traffic selectors against addrblock constraints. + */ +struct addrblock_narrow_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a addrblock_narrow_t. + */ + void (*destroy)(addrblock_narrow_t *this); +}; + +/** + * Create a addrblock_narrow instance. + */ +addrblock_narrow_t *addrblock_narrow_create(); + +#endif /** ADDRBLOCK_NARROW_H_ @}*/ diff --git a/src/libcharon/plugins/addrblock/addrblock_plugin.c b/src/libcharon/plugins/addrblock/addrblock_plugin.c new file mode 100644 index 000000000..1c407035d --- /dev/null +++ b/src/libcharon/plugins/addrblock/addrblock_plugin.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "addrblock_plugin.h" + +#include <daemon.h> + +#include "addrblock_validator.h" +#include "addrblock_narrow.h" + +typedef struct private_addrblock_plugin_t private_addrblock_plugin_t; + +/** + * private data of addrblock_plugin + */ +struct private_addrblock_plugin_t { + + /** + * public functions + */ + addrblock_plugin_t public; + + /** + * Validator implementation instance. + */ + addrblock_validator_t *validator; + + /** + * Listener to check TS list + */ + addrblock_narrow_t *narrower; +}; + +METHOD(plugin_t, destroy, void, + private_addrblock_plugin_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->narrower->listener); + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + this->narrower->destroy(this->narrower); + this->validator->destroy(this->validator); + free(this); +} + +/* + * see header file + */ +plugin_t *addrblock_plugin_create() +{ + private_addrblock_plugin_t *this; + + INIT(this, + .public.plugin.destroy = _destroy, + .validator = addrblock_validator_create(), + .narrower = addrblock_narrow_create(), + ); + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + charon->bus->add_listener(charon->bus, &this->narrower->listener); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/resolve/resolve_plugin.h b/src/libcharon/plugins/addrblock/addrblock_plugin.h index 0148b10d7..87bd516f9 100644 --- a/src/libcharon/plugins/resolve/resolve_plugin.h +++ b/src/libcharon/plugins/addrblock/addrblock_plugin.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -14,29 +14,29 @@ */ /** - * @defgroup resolve resolve + * @defgroup addrblock addrblock * @ingroup cplugins * - * @defgroup resolve_plugin resolve_plugin - * @{ @ingroup resolve + * @defgroup addrblock_plugin addrblock_plugin + * @{ @ingroup addrblock */ -#ifndef RESOLVE_PLUGIN_H_ -#define RESOLVE_PLUGIN_H_ +#ifndef ADDRBLOCK_PLUGIN_H_ +#define ADDRBLOCK_PLUGIN_H_ #include <plugins/plugin.h> -typedef struct resolve_plugin_t resolve_plugin_t; +typedef struct addrblock_plugin_t addrblock_plugin_t; /** - * Plugin that writes received DNS servers in a resolv.conf file. + * RFC 3779 address block checking. */ -struct resolve_plugin_t { +struct addrblock_plugin_t { /** - * implements plugin interface + * Implements plugin_t. interface. */ plugin_t plugin; }; -#endif /** RESOLVE_PLUGIN_H_ @}*/ +#endif /** ADDRBLOCK_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c new file mode 100644 index 000000000..44ef38d85 --- /dev/null +++ b/src/libcharon/plugins/addrblock/addrblock_validator.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * Copyright (C) 2009 Andreas Steffen + * 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 "addrblock_validator.h" + +#include <debug.h> +#include <credentials/certificates/x509.h> +#include <selectors/traffic_selector.h> + +typedef struct private_addrblock_validator_t private_addrblock_validator_t; + +/** + * Private data of an addrblock_validator_t object. + */ +struct private_addrblock_validator_t { + + /** + * Public addrblock_validator_t interface. + */ + addrblock_validator_t public; +}; + +/** + * Do the addrblock check for two x509 plugins + */ +static bool check_addrblock(x509_t *subject, x509_t *issuer) +{ + bool subject_const, issuer_const, contained = TRUE; + enumerator_t *subject_enumerator, *issuer_enumerator; + traffic_selector_t *subject_ts, *issuer_ts; + + subject_const = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS; + issuer_const = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS; + + if (!subject_const && !issuer_const) + { + return TRUE; + } + if (!subject_const) + { + DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension"); + return FALSE; + } + if (!issuer_const) + { + DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension"); + return FALSE; + } + subject_enumerator = subject->create_ipAddrBlock_enumerator(subject); + while (subject_enumerator->enumerate(subject_enumerator, &subject_ts)) + { + contained = FALSE; + + issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer); + while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts)) + { + if (subject_ts->is_contained_in(subject_ts, issuer_ts)) + { + DBG2(DBG_CFG, " subject address block %R is contained in " + "issuer address block %R", subject_ts, issuer_ts); + contained = TRUE; + break; + } + } + issuer_enumerator->destroy(issuer_enumerator); + if (!contained) + { + DBG1(DBG_CFG, "subject address block %R is not contained in any " + "issuer address block", subject_ts); + break; + } + } + subject_enumerator->destroy(subject_enumerator); + return contained; +} + +METHOD(cert_validator_t, validate, bool, + private_addrblock_validator_t *this, certificate_t *subject, + certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth) +{ + if (subject->get_type(subject) == CERT_X509 && + issuer->get_type(issuer) == CERT_X509) + { + return check_addrblock((x509_t*)subject, (x509_t*)issuer); + } + return TRUE; +} + +METHOD(addrblock_validator_t, destroy, void, + private_addrblock_validator_t *this) +{ + free(this); +} + +/** + * See header + */ +addrblock_validator_t *addrblock_validator_create() +{ + private_addrblock_validator_t *this; + + INIT(this, + .public = { + .validator.validate = _validate, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.h b/src/libcharon/plugins/addrblock/addrblock_validator.h new file mode 100644 index 000000000..423f0d41a --- /dev/null +++ b/src/libcharon/plugins/addrblock/addrblock_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup addrblock_validator addrblock_validator + * @{ @ingroup addrblock + */ + +#ifndef ADDRBLOCK_VALIDATOR_H_ +#define ADDRBLOCK_VALIDATOR_H_ + +#include <credentials/cert_validator.h> + +typedef struct addrblock_validator_t addrblock_validator_t; + +/** + * RFC 3779 address block X509 certificate validator. + */ +struct addrblock_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a addrblock_validator_t. + */ + void (*destroy)(addrblock_validator_t *this); +}; + +/** + * Create a addrblock_validator instance. + */ +addrblock_validator_t *addrblock_validator_create(); + +#endif /** ADDRBLOCK_VALIDATOR_H_ @}*/ diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am index e8423589c..b922ef4af 100644 --- a/src/libcharon/plugins/android/Makefile.am +++ b/src/libcharon/plugins/android/Makefile.am @@ -12,7 +12,10 @@ endif libstrongswan_android_la_SOURCES = \ android_plugin.c android_plugin.h \ - android_handler.c android_handler.h + android_service.c android_service.h \ + android_handler.c android_handler.h \ + android_logger.c android_logger.h \ + android_creds.c android_creds.h libstrongswan_android_la_LDFLAGS = -module -avoid-version libstrongswan_android_la_LIBADD = -lcutils diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in index 9f12a9c75..6e4903ee1 100644 --- a/src/libcharon/plugins/android/Makefile.in +++ b/src/libcharon/plugins/android/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -75,7 +75,8 @@ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) libstrongswan_android_la_DEPENDENCIES = am_libstrongswan_android_la_OBJECTS = android_plugin.lo \ - android_handler.lo + android_service.lo android_handler.lo android_logger.lo \ + android_creds.lo libstrongswan_android_la_OBJECTS = \ $(am_libstrongswan_android_la_OBJECTS) libstrongswan_android_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -265,7 +266,10 @@ AM_CFLAGS = -rdynamic @MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android.la libstrongswan_android_la_SOURCES = \ android_plugin.c android_plugin.h \ - android_handler.c android_handler.h + android_service.c android_service.h \ + android_handler.c android_handler.h \ + android_logger.c android_logger.h \ + android_creds.c android_creds.h libstrongswan_android_la_LDFLAGS = -module -avoid-version libstrongswan_android_la_LIBADD = -lcutils @@ -352,8 +356,11 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_creds.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_handler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_service.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c new file mode 100644 index 000000000..aa7fc6f92 --- /dev/null +++ b/src/libcharon/plugins/android/android_creds.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 <keystore_get.h> + +#include "android_creds.h" + +#include <daemon.h> +#include <threading/rwlock.h> + +typedef struct private_android_creds_t private_android_creds_t; + +/** + * Private data of an android_creds_t object + */ +struct private_android_creds_t { + + /** + * Public interface + */ + android_creds_t public; + + /** + * List of trusted certificates, certificate_t* + */ + linked_list_t *certs; + + /** + * User name (ID) + */ + identification_t *user; + + /** + * User password + */ + char *pass; + + /** + * read/write lock + */ + rwlock_t *lock; + +}; + +/** + * Certificate enumerator data + */ +typedef struct { + private_android_creds_t *this; + key_type_t key; + identification_t *id; +} cert_data_t; + +/** + * Filter function for certificates enumerator + */ +static bool cert_filter(cert_data_t *data, certificate_t **in, + certificate_t **out) +{ + certificate_t *cert = *in; + public_key_t *public; + + public = cert->get_public_key(cert); + if (!public) + { + return FALSE; + } + if (data->key != KEY_ANY && public->get_type(public) != data->key) + { + public->destroy(public); + return FALSE; + } + if (data->id && data->id->get_type(data->id) == ID_KEY_ID && + public->has_fingerprint(public, data->id->get_encoding(data->id))) + { + public->destroy(public); + *out = cert; + return TRUE; + } + public->destroy(public); + if (data->id && !cert->has_subject(cert, data->id)) + { + return FALSE; + } + *out = cert; + return TRUE; +} + +/** + * Destroy certificate enumerator data + */ +static void cert_data_destroy(cert_data_t *this) +{ + this->this->lock->unlock(this->this->lock); + free(this); +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_android_creds_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + if (cert == CERT_X509 || cert == CERT_ANY) + { + cert_data_t *data; + this->lock->read_lock(this->lock); + INIT(data, .this = this, .id = id, .key = key); + return enumerator_create_filter( + this->certs->create_enumerator(this->certs), + (void*)cert_filter, data, (void*)cert_data_destroy); + } + return NULL; +} + +/** + * Shared key enumerator implementation + */ +typedef struct { + enumerator_t public; + private_android_creds_t *this; + shared_key_t *key; + bool done; +} shared_enumerator_t; + +METHOD(enumerator_t, shared_enumerate, bool, + shared_enumerator_t *this, shared_key_t **key, id_match_t *me, + id_match_t *other) +{ + if (this->done) + { + return FALSE; + } + *key = this->key; + *me = ID_MATCH_PERFECT; + *other = ID_MATCH_ANY; + this->done = TRUE; + return TRUE; +} + +METHOD(enumerator_t, shared_destroy, void, + shared_enumerator_t *this) +{ + this->key->destroy(this->key); + this->this->lock->unlock(this->this->lock); + free(this); +} + +METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, + private_android_creds_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) +{ + shared_enumerator_t *enumerator; + + this->lock->read_lock(this->lock); + + if (!this->user || !this->pass) + { + this->lock->unlock(this->lock); + return NULL; + } + if (type != SHARED_EAP && type != SHARED_IKE) + { + this->lock->unlock(this->lock); + return NULL; + } + if (me && !me->equals(me, this->user)) + { + this->lock->unlock(this->lock); + return NULL; + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_shared_enumerate, + .destroy = _shared_destroy, + }, + .this = this, + .done = FALSE, + .key = shared_key_create(type, chunk_clone(chunk_create(this->pass, + strlen(this->pass)))), + ); + return &enumerator->public; +} + +METHOD(android_creds_t, add_certificate, bool, + private_android_creds_t *this, char *name) +{ + certificate_t *cert = NULL; + bool status = FALSE; + chunk_t chunk; +#ifdef KEYSTORE_MESSAGE_SIZE + /* most current interface, the eclair interface (without key length) is + * currently not supported */ + char value[KEYSTORE_MESSAGE_SIZE]; + chunk.ptr = value; + chunk.len = keystore_get(name, strlen(name), chunk.ptr); + if (chunk.len > 0) +#else + /* 1.6 interface, allocates memory */ + chunk.ptr = keystore_get(name, &chunk.len); + if (chunk.ptr) +#endif /* KEYSTORE_MESSAGE_SIZE */ + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_PEM, chunk, BUILD_END); + if (cert) + { + this->lock->write_lock(this->lock); + this->certs->insert_last(this->certs, cert); + this->lock->unlock(this->lock); + status = TRUE; + } +#ifndef KEYSTORE_MESSAGE_SIZE + free(chunk.ptr); +#endif /* KEYSTORE_MESSAGE_SIZE */ + } + return status; +} + +METHOD(android_creds_t, set_username_password, void, + private_android_creds_t *this, identification_t *id, char *password) +{ + this->lock->write_lock(this->lock); + DESTROY_IF(this->user); + this->user = id->clone(id); + free(this->pass); + this->pass = password ? strdup(password) : NULL; + this->lock->unlock(this->lock); +} + +METHOD(android_creds_t, clear, void, + private_android_creds_t *this) +{ + certificate_t *cert; + this->lock->write_lock(this->lock); + while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS) + { + cert->destroy(cert); + } + DESTROY_IF(this->user); + free(this->pass); + this->user = NULL; + this->pass = NULL; + this->lock->unlock(this->lock); +} + +METHOD(android_creds_t, destroy, void, + private_android_creds_t *this) +{ + clear(this); + this->certs->destroy(this->certs); + this->lock->destroy(this->lock); + free(this); +} + +/** + * Described in header. + */ +android_creds_t *android_creds_create() +{ + private_android_creds_t *this; + + INIT(this, + .public = { + .set = { + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = _create_shared_enumerator, + .create_private_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .add_certificate = _add_certificate, + .set_username_password = _set_username_password, + .clear = _clear, + .destroy = _destroy, + }, + .certs = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/android/android_creds.h b/src/libcharon/plugins/android/android_creds.h new file mode 100644 index 000000000..0f7b8e0ea --- /dev/null +++ b/src/libcharon/plugins/android/android_creds.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 android_creds android_creds + * @{ @ingroup android + */ + +#ifndef ANDROID_CREDS_H_ +#define ANDROID_CREDS_H_ + +#include <credentials/credential_set.h> + +typedef struct android_creds_t android_creds_t; + +/** + * Android credentials helper. + */ +struct android_creds_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Add a trusted CA certificate from the Android keystore to serve by + * this set. + * + * @param name name/ID of the certificate in the keystore + * @return FALSE if the certificate does not exist or is invalid + */ + bool (*add_certificate)(android_creds_t *this, char *name); + + /** + * Set the username and password for authentication. + * + * @param id ID of the user + * @param password password to use for authentication + */ + void (*set_username_password)(android_creds_t *this, identification_t *id, + char *password); + + /** + * Clear the stored credentials. + */ + void (*clear)(android_creds_t *this); + + /** + * Destroy a android_creds instance. + */ + void (*destroy)(android_creds_t *this); + +}; + +/** + * Create an android_creds instance. + */ +android_creds_t *android_creds_create(); + +#endif /** ANDROID_CREDS_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c index a475eeaab..ec3ff7a51 100644 --- a/src/libcharon/plugins/android/android_handler.c +++ b/src/libcharon/plugins/android/android_handler.c @@ -75,7 +75,7 @@ host_t *get_dns_server(int index) host_t *dns = NULL; char key[10], value[PROPERTY_VALUE_MAX]; - if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key)) + if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key)) { return NULL; } @@ -94,7 +94,7 @@ bool set_dns_server(int index, host_t *dns) { char key[10], value[PROPERTY_VALUE_MAX]; - if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key)) + if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key)) { return FALSE; } diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android/android_logger.c new file mode 100644 index 000000000..43c56e656 --- /dev/null +++ b/src/libcharon/plugins/android/android_logger.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <string.h> +#include <android/log.h> + +#include "android_logger.h" + +#include <library.h> +#include <daemon.h> + +typedef struct private_android_logger_t private_android_logger_t; + +/** + * Private data of an android_logger_t object + */ +struct private_android_logger_t { + + /** + * Public interface + */ + android_logger_t public; + + /** + * logging level + */ + int level; + +}; + + +METHOD(listener_t, log_, bool, + private_android_logger_t *this, debug_t group, level_t level, + int thread, ike_sa_t* ike_sa, char *format, va_list args) +{ + if (level <= this->level) + { + char sgroup[16], buffer[8192]; + char *current = buffer, *next; + snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group); + vsnprintf(buffer, sizeof(buffer), format, args); + while (current) + { /* log each line seperately */ + next = strchr(current, '\n'); + if (next) + { + *(next++) = '\0'; + } + __android_log_print(ANDROID_LOG_INFO, "charon", "%.2d[%s] %s\n", + thread, sgroup, current); + current = next; + } + } + /* always stay registered */ + return TRUE; +} + +METHOD(android_logger_t, destroy, void, + private_android_logger_t *this) +{ + free(this); +} + +/** + * Described in header. + */ +android_logger_t *android_logger_create() +{ + private_android_logger_t *this; + + INIT(this, + .public = { + .listener = { + .log = _log_, + }, + .destroy = _destroy, + }, + .level = lib->settings->get_int(lib->settings, + "charon.plugins.android.loglevel", 1), + ); + + return &this->public; +} + diff --git a/src/libcharon/plugins/resolve/resolve_handler.h b/src/libcharon/plugins/android/android_logger.h index 77bf9781c..c6fe5aff3 100644 --- a/src/libcharon/plugins/resolve/resolve_handler.h +++ b/src/libcharon/plugins/android/android_logger.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Martin Willi + * Copyright (C) 2010 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,36 +14,39 @@ */ /** - * @defgroup resolve_handler resolve_handler - * @{ @ingroup resolve + * @defgroup android_logger android_logger + * @{ @ingroup android */ -#ifndef RESOLVE_HANDLER_H_ -#define RESOLVE_HANDLER_H_ +#ifndef ANDROID_LOGGER_H_ +#define ANDROID_LOGGER_H_ -#include <attributes/attribute_handler.h> +#include <bus/bus.h> -typedef struct resolve_handler_t resolve_handler_t; +typedef struct android_logger_t android_logger_t; /** - * Handle DNS configuration attributes by mangling a resolv.conf file. + * Android specific logger. */ -struct resolve_handler_t { +struct android_logger_t { /** - * Implements the attribute_handler_t interface + * Implements bus_listener_t interface */ - attribute_handler_t handler; + listener_t listener; /** - * Destroy a resolve_handler_t. + * Destroy the logger. */ - void (*destroy)(resolve_handler_t *this); + void (*destroy)(android_logger_t *this); + }; /** - * Create a resolve_handler instance. + * Create an Android specific logger instance. + * + * @return logger instance */ -resolve_handler_t *resolve_handler_create(); +android_logger_t *android_logger_create(); -#endif /** RESOLVE_HANDLER_H_ @}*/ +#endif /** ANDROID_LOGGER_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c index 9a558f53b..e2c8572ef 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android/android_plugin.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Tobias Brunner * Copyright (C) 2010 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -14,7 +15,10 @@ */ #include "android_plugin.h" +#include "android_logger.h" #include "android_handler.h" +#include "android_creds.h" +#include "android_service.h" #include <hydra.h> #include <daemon.h> @@ -32,16 +36,38 @@ struct private_android_plugin_t { android_plugin_t public; /** + * Android specific logger + */ + android_logger_t *logger; + + /** * Android specific DNS handler */ android_handler_t *handler; + + /** + * Android specific credential set + */ + android_creds_t *creds; + + /** + * Service that interacts with the Android Settings frontend + */ + android_service_t *service; + }; METHOD(plugin_t, destroy, void, - private_android_plugin_t *this) + private_android_plugin_t *this) { - hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); + hydra->attributes->remove_handler(hydra->attributes, + &this->handler->handler); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + charon->bus->remove_listener(charon->bus, &this->logger->listener); + this->creds->destroy(this->creds); this->handler->destroy(this->handler); + this->logger->destroy(this->logger); + DESTROY_IF(this->service); free(this); } @@ -56,11 +82,22 @@ plugin_t *android_plugin_create() .public.plugin = { .destroy = _destroy, }, + .logger = android_logger_create(), .handler = android_handler_create(), + .creds = android_creds_create(), ); + charon->bus->add_listener(charon->bus, &this->logger->listener); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); + this->service = android_service_create(this->creds); + if (!this->service) + { + destroy(this); + return NULL; + } + return &this->public.plugin; } diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c new file mode 100644 index 000000000..538c4a9a2 --- /dev/null +++ b/src/libcharon/plugins/android/android_service.c @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 <unistd.h> +#include <cutils/sockets.h> +#include <cutils/properties.h> +#include <signal.h> + +#include "android_service.h" + +#include <daemon.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_android_service_t private_android_service_t; + +/** + * private data of Android service + */ +struct private_android_service_t { + + /** + * public interface + */ + android_service_t public; + + /** + * current IKE_SA + */ + ike_sa_t *ike_sa; + + /** + * job that handles requests from the Android control socket + */ + callback_job_t *job; + + /** + * android credentials + */ + android_creds_t *creds; + + /** + * android control socket + */ + int control; + +}; + +/** + * Some of the error codes defined in VpnManager.java + */ +typedef enum { + /** Error code to indicate an error from authentication. */ + VPN_ERROR_AUTH = 51, + /** Error code to indicate the connection attempt failed. */ + VPN_ERROR_CONNECTION_FAILED = 101, + /** Error code to indicate an error of remote server hanging up. */ + VPN_ERROR_REMOTE_HUNG_UP = 7, + /** Error code to indicate an error of losing connectivity. */ + VPN_ERROR_CONNECTION_LOST = 103, +} android_vpn_errors_t; + +/** + * send a status code back to the Android app + */ +static void send_status(private_android_service_t *this, u_char code) +{ + DBG1(DBG_CFG, "status of Android plugin changed: %d", code); + send(this->control, &code, 1, 0); +} + +METHOD(listener_t, ike_updown, bool, + private_android_service_t *this, ike_sa_t *ike_sa, bool up) +{ + /* this callback is only registered during initiation, so if the IKE_SA + * goes down we assume an authentication error */ + if (this->ike_sa == ike_sa && !up) + { + send_status(this, VPN_ERROR_AUTH); + return FALSE; + } + return TRUE; +} + +METHOD(listener_t, child_state_change, bool, + private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + child_sa_state_t state) +{ + /* this callback is only registered during initiation, so we still have + * the control socket open */ + if (this->ike_sa == ike_sa && state == CHILD_DESTROYING) + { + send_status(this, VPN_ERROR_CONNECTION_FAILED); + return FALSE; + } + return TRUE; +} + +/** + * Callback used to shutdown the daemon + */ +static job_requeue_t shutdown_callback(void *data) +{ + kill(0, SIGTERM); + return JOB_REQUEUE_NONE; +} + +METHOD(listener_t, child_updown, bool, + private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool up) +{ + if (this->ike_sa == ike_sa) + { + if (up) + { + /* disable the hooks registered to catch initiation failures */ + this->public.listener.ike_updown = NULL; + this->public.listener.child_state_change = NULL; + property_set("vpn.status", "ok"); + } + else + { + callback_job_t *job; + /* the control socket is closed as soon as vpn.status is set to "ok" + * and the daemon proxy then only checks for terminated daemons to + * detect lost connections, so... */ + DBG1(DBG_CFG, "connection lost, raising delayed SIGTERM"); + /* to avoid any conflicts we send the SIGTERM not directly from this + * callback, but from a different thread. we also delay it to avoid + * a race condition during a regular shutdown */ + job = callback_job_create(shutdown_callback, NULL, NULL, NULL); + charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, 1); + return FALSE; + } + } + return TRUE; +} + +METHOD(listener_t, ike_rekey, bool, + private_android_service_t *this, ike_sa_t *old, ike_sa_t *new) +{ + if (this->ike_sa == old) + { + this->ike_sa = new; + } + return TRUE; +} + +/** + * Read a string argument from the Android control socket + */ +static char *read_argument(int fd, u_char length) +{ + int offset = 0; + char *data = malloc(length + 1); + while (offset < length) + { + int n = recv(fd, &data[offset], length - offset, 0); + if (n < 0) + { + DBG1(DBG_CFG, "failed to read argument from Android" + " control socket: %s", strerror(errno)); + free(data); + return NULL; + } + offset += n; + } + data[length] = '\0'; + DBG3(DBG_CFG, "received argument from Android control socket: %s", data); + return data; +} + +/** + * handle the request received from the Android control socket + */ +static job_requeue_t initiate(private_android_service_t *this) +{ + bool oldstate; + int fd, i = 0; + char *hostname = NULL, *cacert = NULL, *username = NULL, *password = NULL; + identification_t *gateway = NULL, *user = NULL; + ike_cfg_t *ike_cfg; + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg; + traffic_selector_t *ts; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + lifetime_cfg_t lifetime = { + .time = { + .life = 10800, /* 3h */ + .rekey = 10200, /* 2h50min */ + .jitter = 300 /* 5min */ + } + }; + + fd = accept(this->control, NULL, 0); + if (fd < 0) + { + DBG1(DBG_CFG, "accept on Android control socket failed: %s", + strerror(errno)); + return JOB_REQUEUE_NONE; + } + /* the original control socket is not used anymore */ + close(this->control); + this->control = fd; + + while (TRUE) + { + u_char length; + if (recv(fd, &length, 1, 0) != 1) + { + DBG1(DBG_CFG, "failed to read from Android control socket: %s", + strerror(errno)); + return JOB_REQUEUE_NONE; + } + + if (length == 0xFF) + { /* last argument */ + break; + } + else + { + switch (i++) + { + case 0: /* gateway */ + hostname = read_argument(fd, length); + break; + case 1: /* CA certificate name */ + cacert = read_argument(fd, length); + break; + case 2: /* username */ + username = read_argument(fd, length); + break; + case 3: /* password */ + password = read_argument(fd, length); + break; + } + } + } + + if (cacert) + { + if (!this->creds->add_certificate(this->creds, cacert)) + { + DBG1(DBG_CFG, "failed to load CA certificate"); + } + /* if this is a server cert we could use the cert subject as id + * but we have to test first if that possible to configure */ + } + + gateway = identification_create_from_string(hostname); + DBG1(DBG_CFG, "using CA certificate, gateway identitiy '%Y'", gateway); + + if (username) + { + user = identification_create_from_string(username); + this->creds->set_username_password(this->creds, user, password); + } + + ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", IKEV2_UDP_PORT, + hostname, IKEV2_UDP_PORT); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + + peer_cfg = peer_cfg_create("android", 2, ike_cfg, CERT_SEND_IF_ASKED, + UNIQUE_REPLACE, 1, /* keyingtries */ + 36000, 0, /* rekey 10h, reauth none */ + 600, 600, /* jitter, over 10min */ + TRUE, 0, /* mobike, DPD */ + host_create_from_string("0.0.0.0", 0) /* virt */, + NULL, FALSE, NULL, NULL); /* pool, mediation */ + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); + auth->add(auth, AUTH_RULE_IDENTITY, user); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + auth->add(auth, AUTH_RULE_IDENTITY, gateway); + peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); + + child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL, + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + ts = traffic_selector_create_dynamic(0, 0, 65535); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts); + ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0", + 0, "255.255.255.255", 65535); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + /* get an additional reference because initiate consumes one */ + child_cfg->get_ref(child_cfg); + + /* get us an IKE_SA */ + ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, + peer_cfg); + if (!ike_sa->get_peer_cfg(ike_sa)) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + } + peer_cfg->destroy(peer_cfg); + + /* store the IKE_SA so we can track its progress */ + this->ike_sa = ike_sa; + + /* confirm that we received the request */ + send_status(this, i); + + if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) + { + DBG1(DBG_CFG, "failed to initiate tunnel"); + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + send_status(this, VPN_ERROR_CONNECTION_FAILED); + return JOB_REQUEUE_NONE; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return JOB_REQUEUE_NONE; +} + +METHOD(android_service_t, destroy, void, + private_android_service_t *this) +{ + charon->bus->remove_listener(charon->bus, &this->public.listener); + close(this->control); + free(this); +} + +/** + * See header + */ +android_service_t *android_service_create(android_creds_t *creds) +{ + private_android_service_t *this; + + INIT(this, + .public = { + .listener = { + .ike_updown = _ike_updown, + .child_state_change = _child_state_change, + .child_updown = _child_updown, + .ike_rekey = _ike_rekey, + }, + .destroy = _destroy, + }, + .creds = creds, + ); + + this->control = android_get_control_socket("charon"); + if (this->control == -1) + { + DBG1(DBG_CFG, "failed to get Android control socket"); + free(this); + return NULL; + } + + if (listen(this->control, 1) < 0) + { + DBG1(DBG_CFG, "failed to listen on Android control socket: %s", + strerror(errno)); + close(this->control); + free(this); + return NULL; + } + + charon->bus->add_listener(charon->bus, &this->public.listener); + this->job = callback_job_create((callback_job_cb_t)initiate, this, + NULL, NULL); + charon->processor->queue_job(charon->processor, (job_t*)this->job); + + return &this->public; +} + diff --git a/src/libcharon/plugins/android/android_service.h b/src/libcharon/plugins/android/android_service.h new file mode 100644 index 000000000..d096d6cd5 --- /dev/null +++ b/src/libcharon/plugins/android/android_service.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 android_service android_service + * @{ @ingroup android + */ + +#ifndef ANDROID_SERVICE_H_ +#define ANDROID_SERVICE_H_ + +typedef struct android_service_t android_service_t; + +#include <bus/listeners/listener.h> + +#include "android_creds.h" + +/** + * Service that interacts with the Android Settings frontend. + */ +struct android_service_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy a android_service_t. + */ + void (*destroy)(android_service_t *this); + +}; + +/** + * Create an Android service instance. + * + * @param creds Android credentials + */ +android_service_t *android_service_create(android_creds_t *creds); + +#endif /** ANDROID_SERVICE_H_ @}*/ diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index 7606b963c..b34654fb7 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c index dbcceb6ce..a6a887780 100644 --- a/src/libcharon/plugins/dhcp/dhcp_provider.c +++ b/src/libcharon/plugins/dhcp/dhcp_provider.c @@ -129,7 +129,8 @@ METHOD(attribute_provider_t, release_address, bool, } METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, - private_dhcp_provider_t *this, identification_t *id, host_t *vip) + private_dhcp_provider_t *this, char *pool, identification_t *id, + host_t *vip) { dhcp_transaction_t *transaction; diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index 1cea81a9b..14bf3f15d 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c index 26546809d..dfcc69710 100644 --- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c +++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c @@ -421,7 +421,6 @@ static status_t process_notification(private_eap_aka_peer_t *this, /* test success bit */ if (!(data.ptr[0] & 0x80)) { - success = FALSE; DBG1(DBG_IKE, "received EAP-AKA notification error '%N'", simaka_notification_names, code); } diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index d0b0f5601..b41b59616 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c index 9817fff8f..a9767ad91 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c +++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c @@ -52,8 +52,7 @@ bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN]) shared_key_t *shared; chunk_t key; - shared = charon->credentials->get_shared(charon->credentials, - SHARED_EAP, id, NULL); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL); if (shared == NULL) { return FALSE; diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 110e1528b..57952f621 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c index c7f55fa70..f641ad13a 100644 --- a/src/libcharon/plugins/eap_gtc/eap_gtc.c +++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c @@ -168,8 +168,8 @@ static status_t process_peer(private_eap_gtc_t *this, chunk_t key; size_t len; - shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP, - this->peer, this->server); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, + this->peer, this->server); if (shared == NULL) { DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'", diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index bbb987dd6..d78957438 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index 943811604..5bfc59fa4 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c index 0eda8f755..3554ae12e 100644 --- a/src/libcharon/plugins/eap_md5/eap_md5.c +++ b/src/libcharon/plugins/eap_md5/eap_md5.c @@ -85,8 +85,7 @@ static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response, chunk_t concat; hasher_t *hasher; - shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP, - me, other); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other); if (shared == NULL) { DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'", me, other); diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index 2f6c65df4..d61cc9e5d 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c index c1ccf72eb..3cd8d994c 100644 --- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c +++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c @@ -614,8 +614,7 @@ static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me, chunk_t password; /* try to find a stored NT_HASH first */ - shared = charon->credentials->get_shared(charon->credentials, - SHARED_NT_HASH, me, other); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_NT_HASH, me, other); if (shared ) { *nt_hash = chunk_clone(shared->get_key(shared)); @@ -624,8 +623,7 @@ static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me, } /* fallback to plaintext password */ - shared = charon->credentials->get_shared(charon->credentials, - SHARED_EAP, me, other); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other); if (shared) { password = ascii_to_unicode(shared->get_key(shared)); @@ -820,7 +818,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this, eap_mschapv2_header_t *eap; chunk_t data; char *message, *token, *msg = NULL; - int message_len, error, retryable; + int message_len, error = 0, retryable; chunk_t challenge = chunk_empty; data = in->get_data(in); diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am index a3abd4124..afc50bced 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.am +++ b/src/libcharon/plugins/eap_radius/Makefile.am @@ -13,6 +13,8 @@ endif libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ + radius_server.h radius_server.c \ + radius_socket.h radius_socket.c \ radius_client.h radius_client.c \ radius_message.h radius_message.c diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 18427adef..bb372d13c 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -75,7 +75,8 @@ am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) libstrongswan_eap_radius_la_LIBADD = am_libstrongswan_eap_radius_la_OBJECTS = eap_radius_plugin.lo \ - eap_radius.lo radius_client.lo radius_message.lo + eap_radius.lo radius_server.lo radius_socket.lo \ + radius_client.lo radius_message.lo libstrongswan_eap_radius_la_OBJECTS = \ $(am_libstrongswan_eap_radius_la_OBJECTS) libstrongswan_eap_radius_la_LINK = $(LIBTOOL) --tag=CC \ @@ -267,6 +268,8 @@ AM_CFLAGS = -rdynamic libstrongswan_eap_radius_la_SOURCES = \ eap_radius_plugin.h eap_radius_plugin.c \ eap_radius.h eap_radius.c \ + radius_server.h radius_server.c \ + radius_socket.h radius_socket.c \ radius_client.h radius_client.c \ radius_message.h radius_message.c @@ -358,6 +361,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_message.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_server.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_socket.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c index f041fda54..65b868bc6 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius.c +++ b/src/libcharon/plugins/eap_radius/eap_radius.c @@ -53,11 +53,6 @@ struct private_eap_radius_t { u_int32_t vendor; /** - * EAP MSK, if method established one - */ - chunk_t msk; - - /** * RADIUS client instance */ radius_client_t *client; @@ -71,6 +66,11 @@ struct private_eap_radius_t { * Prefix to prepend to EAP identity */ char *id_prefix; + + /** + * Handle the Class attribute as group membership information? + */ + bool class_group; }; /** @@ -140,10 +140,8 @@ static bool radius2ike(private_eap_radius_t *this, return FALSE; } -/** - * Implementation of eap_method_t.initiate - */ -static status_t initiate(private_eap_radius_t *this, eap_payload_t **out) +METHOD(eap_method_t, initiate, status_t, + private_eap_radius_t *this, eap_payload_t **out) { radius_message_t *request, *response; status_t status = FAILED; @@ -177,10 +175,44 @@ static status_t initiate(private_eap_radius_t *this, eap_payload_t **out) } /** - * Implementation of eap_method_t.process + * Handle the Class attribute as group membership information */ -static status_t process(private_eap_radius_t *this, - eap_payload_t *in, eap_payload_t **out) +static void process_class(private_eap_radius_t *this, radius_message_t *msg) +{ + enumerator_t *enumerator; + chunk_t data; + int type; + + enumerator = msg->create_enumerator(msg); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == RAT_CLASS) + { + identification_t *id; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + + if (data.len >= 44) + { /* quirk: ignore long class attributes, these are used for + * other purposes by some RADIUS servers (such as NPS). */ + continue; + } + + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa) + { + auth = ike_sa->get_auth_cfg(ike_sa, FALSE); + id = identification_create_from_data(data); + DBG1(DBG_CFG, "received group membership '%Y' from RADIUS", id); + auth->add(auth, AUTH_RULE_GROUP, id); + } + } + } + enumerator->destroy(enumerator); +} + +METHOD(eap_method_t, process, status_t, + private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out) { radius_message_t *request, *response; status_t status = FAILED; @@ -211,8 +243,10 @@ static status_t process(private_eap_radius_t *this, status = FAILED; break; case RMC_ACCESS_ACCEPT: - this->msk = this->client->decrypt_msk(this->client, - response, request); + if (this->class_group) + { + process_class(this, response); + } status = SUCCESS; break; case RMC_ACCESS_REJECT: @@ -228,32 +262,29 @@ static status_t process(private_eap_radius_t *this, return status; } -/** - * Implementation of eap_method_t.get_type. - */ -static eap_type_t get_type(private_eap_radius_t *this, u_int32_t *vendor) +METHOD(eap_method_t, get_type, eap_type_t, + private_eap_radius_t *this, u_int32_t *vendor) { *vendor = this->vendor; return this->type; } -/** - * Implementation of eap_method_t.get_msk. - */ -static status_t get_msk(private_eap_radius_t *this, chunk_t *msk) +METHOD(eap_method_t, get_msk, status_t, + private_eap_radius_t *this, chunk_t *out) { - if (this->msk.ptr) + chunk_t msk; + + msk = this->client->get_msk(this->client); + if (msk.len) { - *msk = this->msk; + *out = msk; return SUCCESS; } return FAILED; } -/** - * Implementation of eap_method_t.is_mutual. - */ -static bool is_mutual(private_eap_radius_t *this) +METHOD(eap_method_t, is_mutual, bool, + private_eap_radius_t *this) { switch (this->type) { @@ -265,15 +296,12 @@ static bool is_mutual(private_eap_radius_t *this) } } -/** - * Implementation of eap_method_t.destroy. - */ -static void destroy(private_eap_radius_t *this) +METHOD(eap_method_t, destroy, void, + private_eap_radius_t *this) { this->peer->destroy(this->peer); this->server->destroy(this->server); this->client->destroy(this->client); - chunk_clear(&this->msk); free(this); } @@ -282,15 +310,26 @@ static void destroy(private_eap_radius_t *this) */ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer) { - private_eap_radius_t *this = malloc_thing(private_eap_radius_t); - - this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate; - this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process; - this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type; - this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual; - this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk; - this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy; - + private_eap_radius_t *this; + + INIT(this, + .public.eap_method_interface = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .destroy = _destroy, + }, + /* initially EAP_RADIUS, but is set to the method selected by RADIUS */ + .type = EAP_RADIUS, + .eap_start = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-radius.eap_start", FALSE), + .id_prefix = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.id_prefix", ""), + .class_group = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-radius.class_group", FALSE), + ); this->client = radius_client_create(); if (!this->client) { @@ -299,14 +338,6 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer } this->peer = peer->clone(peer); this->server = server->clone(server); - /* initially EAP_RADIUS, but is set to the method selected by RADIUS */ - this->type = EAP_RADIUS; - this->vendor = 0; - this->msk = chunk_empty; - this->eap_start = lib->settings->get_bool(lib->settings, - "charon.plugins.eap-radius.eap_start", FALSE); - this->id_prefix = lib->settings->get_str(lib->settings, - "charon.plugins.eap-radius.id_prefix", ""); return &this->public; } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index 7d2788c3e..91aae2f62 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -17,17 +17,130 @@ #include "eap_radius.h" #include "radius_client.h" +#include "radius_server.h" #include <daemon.h> /** - * Implementation of plugin_t.destroy + * Default RADIUS server port, when not configured */ -static void destroy(eap_radius_plugin_t *this) +#define RADIUS_PORT 1812 + +typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t; + +/** + * Private data of an eap_radius_plugin_t object. + */ +struct private_eap_radius_plugin_t { + + /** + * Public radius_plugin_t interface. + */ + eap_radius_plugin_t public; + + /** + * List of RADIUS servers + */ + linked_list_t *servers; +}; + +/** + * Instance of the EAP plugin + */ +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); - radius_client_cleanup(); + 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) +{ + enumerator_t *enumerator; + radius_server_t *server; + char *nas_identifier, *secret, *address, *section; + int port, sockets, preference; + + address = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.server", NULL); + if (address) + { /* legacy configuration */ + secret = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.secret", NULL); + if (!secret) + { + DBG1(DBG_CFG, "no RADUIS secret defined"); + return FALSE; + } + nas_identifier = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.nas_identifier", "strongSwan"); + port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.port", RADIUS_PORT); + sockets = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.sockets", 1); + server = radius_server_create(address, port, nas_identifier, + secret, sockets, 0); + if (!server) + { + DBG1(DBG_CFG, "no RADUIS server defined"); + return FALSE; + } + this->servers->insert_last(this->servers, server); + return TRUE; + } + + enumerator = lib->settings->create_section_enumerator(lib->settings, + "charon.plugins.eap-radius.servers"); + while (enumerator->enumerate(enumerator, §ion)) + { + address = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.address", NULL, section); + if (!address) + { + DBG1(DBG_CFG, "RADIUS server '%s' misses address, skipped", section); + continue; + } + secret = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.secret", NULL, section); + if (!secret) + { + DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section); + continue; + } + nas_identifier = lib->settings->get_str(lib->settings, + "charon.plugins.eap-radius.servers.%s.nas_identifier", + "strongSwan", section); + port = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section); + sockets = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.sockets", 1, section); + preference = lib->settings->get_int(lib->settings, + "charon.plugins.eap-radius.servers.%s.preference", 0, section); + server = radius_server_create(address, port, nas_identifier, + secret, sockets, preference); + if (!server) + { + DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section); + continue; + } + this->servers->insert_last(this->servers, server); + } + enumerator->destroy(enumerator); + + if (this->servers->get_count(this->servers) == 0) + { + DBG1(DBG_CFG, "no valid RADIUS server configuration found"); + return FALSE; + } + return TRUE; } /* @@ -35,20 +148,35 @@ static void destroy(eap_radius_plugin_t *this) */ plugin_t *eap_radius_plugin_create() { - eap_radius_plugin_t *this; + private_eap_radius_plugin_t *this; + + INIT(this, + .public.plugin.destroy = _destroy, + .servers = linked_list_create(), + ); - if (!radius_client_init()) + if (!load_servers(this)) { - DBG1(DBG_CFG, "RADIUS plugin initialization failed"); + destroy(this); return NULL; } - - this = malloc_thing(eap_radius_plugin_t); - this->plugin.destroy = (void(*)(plugin_t*))destroy; - charon->eap->add_method(charon->eap, EAP_RADIUS, 0, EAP_SERVER, (eap_constructor_t)eap_radius_create); - return &this->plugin; + instance = this; + + return &this->public.plugin; +} + +/** + * See header + */ +enumerator_t *eap_radius_create_server_enumerator() +{ + if (instance) + { + return instance->servers->create_enumerator(instance->servers); + } + return enumerator_create_empty(); } diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h index f2b8b5082..cb724364a 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h @@ -25,6 +25,7 @@ #define EAP_RADIUS_PLUGIN_H_ #include <plugins/plugin.h> +#include <utils/enumerator.h> typedef struct eap_radius_plugin_t eap_radius_plugin_t; @@ -42,4 +43,11 @@ struct eap_radius_plugin_t { plugin_t plugin; }; +/** + * Create an enumerator over all loaded RADIUS servers. + * + * @return enumerator over radius_server_t + */ +enumerator_t *eap_radius_create_server_enumerator(); + #endif /** EAP_RADIUS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c index 1d1f21742..232b9135e 100644 --- a/src/libcharon/plugins/eap_radius/radius_client.c +++ b/src/libcharon/plugins/eap_radius/radius_client.c @@ -15,6 +15,9 @@ #include "radius_client.h" +#include "eap_radius_plugin.h" +#include "radius_server.h" + #include <unistd.h> #include <errno.h> @@ -24,42 +27,8 @@ #include <threading/condvar.h> #include <threading/mutex.h> -/** - * Default RADIUS server port, when not configured - */ -#define RADIUS_PORT 1812 - -/** - * Vendor-Id of Microsoft specific attributes - */ -#define VENDOR_ID_MICROSOFT 311 - -/** - * Microsoft specific vendor attributes - */ -#define MS_MPPE_SEND_KEY 16 -#define MS_MPPE_RECV_KEY 17 - typedef struct private_radius_client_t private_radius_client_t; -typedef struct entry_t entry_t; - -/** - * A socket pool entry. - */ -struct entry_t { - /** socket file descriptor */ - int fd; - /** current RADIUS identifier */ - u_int8_t identifier; - /** hasher to use for response verification */ - hasher_t *hasher; - /** HMAC-MD5 signer to build Message-Authenticator attribute */ - signer_t *signer; - /** random number generator for RADIUS request authenticator */ - rng_t *rng; -}; - /** * Private data of an radius_client_t object. */ @@ -71,170 +40,20 @@ struct private_radius_client_t { radius_client_t public; /** + * Selected RADIUS server + */ + radius_server_t *server; + + /** * RADIUS servers State attribute */ chunk_t state; -}; -/** - * Global list of radius sockets, contains entry_t's - */ -static linked_list_t *sockets; - -/** - * mutex to lock sockets list - */ -static mutex_t *mutex; - -/** - * condvar to wait for sockets - */ -static condvar_t *condvar; - -/** - * RADIUS secret - */ -static chunk_t secret; - -/** - * NAS-Identifier - */ -static chunk_t nas_identifier; - -/** - * Clean up socket list - */ -void radius_client_cleanup() -{ - entry_t *entry; - - mutex->destroy(mutex); - condvar->destroy(condvar); - while (sockets->remove_last(sockets, (void**)&entry) == SUCCESS) - { - entry->rng->destroy(entry->rng); - entry->hasher->destroy(entry->hasher); - entry->signer->destroy(entry->signer); - close(entry->fd); - free(entry); - } - sockets->destroy(sockets); -} - -/** - * Initialize the socket list - */ -bool radius_client_init() -{ - int i, count, fd; - u_int16_t port; - entry_t *entry; - host_t *host; - char *server; - - nas_identifier.ptr = lib->settings->get_str(lib->settings, - "charon.plugins.eap-radius.nas_identifier", "strongSwan"); - nas_identifier.len = strlen(nas_identifier.ptr); - - secret.ptr = lib->settings->get_str(lib->settings, - "charon.plugins.eap-radius.secret", NULL); - if (!secret.ptr) - { - DBG1(DBG_CFG, "no RADUIS secret defined"); - return FALSE; - } - secret.len = strlen(secret.ptr); - server = lib->settings->get_str(lib->settings, - "charon.plugins.eap-radius.server", NULL); - if (!server) - { - DBG1(DBG_CFG, "no RADUIS server defined"); - return FALSE; - } - port = lib->settings->get_int(lib->settings, - "charon.plugins.eap-radius.port", RADIUS_PORT); - host = host_create_from_dns(server, 0, port); - if (!host) - { - return FALSE; - } - count = lib->settings->get_int(lib->settings, - "charon.plugins.eap-radius.sockets", 1); - - sockets = linked_list_create(); - mutex = mutex_create(MUTEX_TYPE_DEFAULT); - condvar = condvar_create(CONDVAR_TYPE_DEFAULT); - for (i = 0; i < count; i++) - { - fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) - { - DBG1(DBG_CFG, "opening RADIUS socket failed"); - host->destroy(host); - radius_client_cleanup(); - return FALSE; - } - if (connect(fd, host->get_sockaddr(host), - *host->get_sockaddr_len(host)) < 0) - { - DBG1(DBG_CFG, "connecting RADIUS socket failed"); - host->destroy(host); - radius_client_cleanup(); - return FALSE; - } - entry = malloc_thing(entry_t); - entry->fd = fd; - /* we use per-socket crypto elements: this reduces overhead, but - * is still thread-save. */ - entry->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - entry->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128); - entry->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); - if (!entry->hasher || !entry->signer || !entry->rng) - { - DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required"); - DESTROY_IF(entry->hasher); - DESTROY_IF(entry->signer); - DESTROY_IF(entry->rng); - free(entry); - host->destroy(host); - radius_client_cleanup(); - return FALSE; - } - entry->signer->set_key(entry->signer, secret); - /* we use a random identifier, helps if we restart often (testing) */ - entry->identifier = random(); - sockets->insert_last(sockets, entry); - } - host->destroy(host); - return TRUE; -} - -/** - * Get a socket from the pool, block if none available - */ -static entry_t* get_socket() -{ - entry_t *entry; - - mutex->lock(mutex); - while (sockets->remove_first(sockets, (void**)&entry) != SUCCESS) - { - condvar->wait(condvar, mutex); - } - mutex->unlock(mutex); - return entry; -} - -/** - * Release a socket to the pool - */ -static void put_socket(entry_t *entry) -{ - mutex->lock(mutex); - sockets->insert_last(sockets, entry); - mutex->unlock(mutex); - condvar->signal(condvar); -} + /** + * EAP MSK, from MPPE keys + */ + chunk_t msk; +}; /** * Save the state attribute to include in further request @@ -261,234 +80,103 @@ static void save_state(private_radius_client_t *this, radius_message_t *msg) chunk_free(&this->state); } -/** - * Implementation of radius_client_t.request - */ -static radius_message_t* request(private_radius_client_t *this, - radius_message_t *req) +METHOD(radius_client_t, request, radius_message_t*, + private_radius_client_t *this, radius_message_t *req) { char virtual[] = {0x00,0x00,0x00,0x05}; - entry_t *socket; - chunk_t data; - int i; + radius_socket_t *socket; + radius_message_t *res; - socket = get_socket(); - - /* set Message Identifier */ - req->set_identifier(req, socket->identifier++); /* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */ req->add(req, RAT_NAS_PORT_TYPE, chunk_create(virtual, sizeof(virtual))); /* add our NAS-Identifier */ - req->add(req, RAT_NAS_IDENTIFIER, nas_identifier); + req->add(req, RAT_NAS_IDENTIFIER, + this->server->get_nas_identifier(this->server)); /* add State attribute, if server sent one */ if (this->state.ptr) { req->add(req, RAT_STATE, this->state); } - /* sign the request */ - req->sign(req, socket->rng, socket->signer); - - data = req->get_encoding(req); - /* timeout after 2, 3, 4, 5 seconds */ - for (i = 2; i <= 5; i++) + 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)); + res = socket->request(socket, req); + if (res) { - radius_message_t *response; - bool retransmit = FALSE; - struct timeval tv; - char buf[4096]; - fd_set fds; - int res; - - if (send(socket->fd, data.ptr, data.len, 0) != data.len) - { - DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); - put_socket(socket); - return NULL; - } - tv.tv_sec = i; - tv.tv_usec = 0; - - while (TRUE) + DBG1(DBG_CFG, "received RADIUS %N from %#H", radius_message_code_names, + res->get_code(res), this->server->get_address(this->server)); + save_state(this, res); + if (res->get_code(res) == RMC_ACCESS_ACCEPT) { - FD_ZERO(&fds); - FD_SET(socket->fd, &fds); - res = select(socket->fd + 1, &fds, NULL, NULL, &tv); - /* TODO: updated tv to time not waited. Linux does this for us. */ - if (res < 0) - { /* failed */ - DBG1(DBG_CFG, "waiting for RADIUS message failed: %s", - strerror(errno)); - break; - } - if (res == 0) - { /* timeout */ - DBG1(DBG_CFG, "retransmitting RADIUS message"); - retransmit = TRUE; - break; - } - res = recv(socket->fd, buf, sizeof(buf), MSG_DONTWAIT); - if (res <= 0) - { - DBG1(DBG_CFG, "receiving RADIUS message failed: %s", - strerror(errno)); - break; - } - response = radius_message_parse_response(chunk_create(buf, res)); - if (response) - { - if (response->verify(response, req->get_authenticator(req), - secret, socket->hasher, socket->signer)) - { - save_state(this, response); - put_socket(socket); - return response; - } - response->destroy(response); - } - DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); - } - if (!retransmit) - { - break; + chunk_clear(&this->msk); + this->msk = socket->decrypt_msk(socket, req, res); } + this->server->put_socket(this->server, socket, TRUE); + return res; } - DBG1(DBG_CFG, "RADIUS server is not responding"); - put_socket(socket); + this->server->put_socket(this->server, socket, FALSE); charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING); return NULL; } -/** - * Decrypt a MS-MPPE-Send/Recv-Key - */ -static chunk_t decrypt_mppe_key(private_radius_client_t *this, u_int16_t salt, - chunk_t C, radius_message_t *request) +METHOD(radius_client_t, get_msk, chunk_t, + private_radius_client_t *this) { - chunk_t A, R, P, seed; - u_char *c, *p; - hasher_t *hasher; - - /** - * From RFC2548 (encryption): - * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) - * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) - * . . . - * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) - */ - - if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5) - { - return chunk_empty; - } - - hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); - if (!hasher) - { - return chunk_empty; - } - - A = chunk_create((u_char*)&salt, sizeof(salt)); - R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); - P = chunk_alloca(C.len); - p = P.ptr; - c = C.ptr; - - seed = chunk_cata("cc", R, A); - - while (c < C.ptr + C.len) - { - /* b(i) = MD5(S + c(i-1)) */ - hasher->get_hash(hasher, secret, NULL); - hasher->get_hash(hasher, seed, p); - - /* p(i) = b(i) xor c(1) */ - memxor(p, c, HASH_SIZE_MD5); - - /* prepare next round */ - seed = chunk_create(c, HASH_SIZE_MD5); - c += HASH_SIZE_MD5; - p += HASH_SIZE_MD5; - } - hasher->destroy(hasher); + return this->msk; +} - /* remove truncation, first byte is key length */ - if (*P.ptr >= P.len) - { /* decryption failed? */ - return chunk_empty; - } - return chunk_clone(chunk_create(P.ptr + 1, *P.ptr)); +METHOD(radius_client_t, destroy, void, + private_radius_client_t *this) +{ + chunk_clear(&this->msk); + free(this->state.ptr); + free(this); } /** - * Implementation of radius_client_t.decrypt_msk + * See header */ -static chunk_t decrypt_msk(private_radius_client_t *this, - radius_message_t *response, radius_message_t *request) +radius_client_t *radius_client_create() { - struct { - u_int32_t id; - u_int8_t type; - u_int8_t length; - u_int16_t salt; - u_int8_t key[]; - } __attribute__((packed)) *mppe_key; + private_radius_client_t *this; enumerator_t *enumerator; - chunk_t data, send = chunk_empty, recv = chunk_empty; - int type; - - enumerator = response->create_enumerator(response); - while (enumerator->enumerate(enumerator, &type, &data)) + radius_server_t *server; + int current, best = -1; + + INIT(this, + .public = { + .request = _request, + .get_msk = _get_msk, + .destroy = _destroy, + }, + ); + + enumerator = eap_radius_create_server_enumerator(); + while (enumerator->enumerate(enumerator, &server)) { - if (type == RAT_VENDOR_SPECIFIC && - data.len > sizeof(*mppe_key)) + current = server->get_preference(server); + if (current > best || + /* for two with equal preference, 50-50 chance */ + (current == best && random() % 2 == 0)) + { + DBG2(DBG_CFG, "RADIUS server %H is candidate: %d", + server->get_address(server), current); + best = current; + this->server = server; + } + else { - mppe_key = (void*)data.ptr; - if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT && - mppe_key->length == data.len - sizeof(mppe_key->id)) - { - data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key)); - if (mppe_key->type == MS_MPPE_SEND_KEY) - { - send = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - if (mppe_key->type == MS_MPPE_RECV_KEY) - { - recv = decrypt_mppe_key(this, mppe_key->salt, data, request); - } - } + DBG2(DBG_CFG, "RADIUS server %H skipped: %d", + server->get_address(server), current); } } enumerator->destroy(enumerator); - if (send.ptr && recv.ptr) + + if (!this->server) { - return chunk_cat("mm", recv, send); + free(this); + return NULL; } - chunk_clear(&send); - chunk_clear(&recv); - return chunk_empty; -} - -/** - * Implementation of radius_client_t.destroy. - */ -static void destroy(private_radius_client_t *this) -{ - free(this->state.ptr); - free(this); -} - -/** - * See header - */ -radius_client_t *radius_client_create() -{ - private_radius_client_t *this = malloc_thing(private_radius_client_t); - - this->public.request = (radius_message_t*(*)(radius_client_t*, radius_message_t *msg))request; - this->public.decrypt_msk = (chunk_t(*)(radius_client_t*, radius_message_t *, radius_message_t *))decrypt_msk; - this->public.destroy = (void(*)(radius_client_t*))destroy; - - this->state = chunk_empty; return &this->public; } diff --git a/src/libcharon/plugins/eap_radius/radius_client.h b/src/libcharon/plugins/eap_radius/radius_client.h index 77ba94807..e4f3a7222 100644 --- a/src/libcharon/plugins/eap_radius/radius_client.h +++ b/src/libcharon/plugins/eap_radius/radius_client.h @@ -29,19 +29,14 @@ typedef struct radius_client_t radius_client_t; * RADIUS client functionality. * * To communicate with a RADIUS server, create a client and send messages over - * it. All instances share a fixed size pool of sockets. The client reserves - * a socket during request() and releases it afterwards. + * it. The client allocates a socket from the best RADIUS server abailable. */ struct radius_client_t { /** * Send a RADIUS request and wait for the response. * - * The client fills in RADIUS Message identifier, NAS-Identifier, - * NAS-Port-Type, builds a Request-Authenticator and calculates the - * Message-Authenticator attribute. - * The received response gets verified using the Response-Identifier - * and the Message-Authenticator attribute. + * The client fills in NAS-Identifier nad NAS-Port-Type * * @param msg RADIUS request message to send * @return response, NULL if timed out/verification failed @@ -49,14 +44,11 @@ struct radius_client_t { radius_message_t* (*request)(radius_client_t *this, radius_message_t *msg); /** - * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key. + * Get the EAP MSK after successful RADIUS authentication. * - * @param response RADIUS response message containing attributes - * @param request associated RADIUS request message - * @return allocated MSK, empty chunk if none found + * @return MSK, allocated */ - chunk_t (*decrypt_msk)(radius_client_t *this, radius_message_t *response, - radius_message_t *request); + chunk_t (*get_msk)(radius_client_t *this); /** * Destroy the client, release the socket. @@ -65,24 +57,10 @@ struct radius_client_t { }; /** - * Create a RADIUS client, acquire a socket. - * - * This call might block if the socket pool is empty. + * Create a RADIUS client. * * @return radius_client_t object */ radius_client_t *radius_client_create(); -/** - * Initialize the socket pool. - * - * @return TRUE if initialization successful - */ -bool radius_client_init(); - -/** - * Cleanup the socket pool. - */ -void radius_client_cleanup(); - #endif /** RADIUS_CLIENT_H_ @}*/ diff --git a/src/libcharon/plugins/eap_radius/radius_message.c b/src/libcharon/plugins/eap_radius/radius_message.c index 11a1d8dfc..23a29b772 100644 --- a/src/libcharon/plugins/eap_radius/radius_message.c +++ b/src/libcharon/plugins/eap_radius/radius_message.c @@ -215,13 +215,8 @@ typedef struct { int left; } attribute_enumerator_t; - -/** - * Implementation of attribute_enumerator_t.enumerate - */ -static bool attribute_enumerate(attribute_enumerator_t *this, - int *type, chunk_t *data) - +METHOD(enumerator_t, attribute_enumerate, bool, + attribute_enumerator_t *this, int *type, chunk_t *data) { if (this->left == 0) { @@ -241,10 +236,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this, return TRUE; } -/** - * Implementation of radius_message_t.create_enumerator - */ -static enumerator_t* create_enumerator(private_radius_message_t *this) +METHOD(radius_message_t, create_enumerator, enumerator_t*, + private_radius_message_t *this) { attribute_enumerator_t *e; @@ -252,20 +245,19 @@ static enumerator_t* create_enumerator(private_radius_message_t *this) { return enumerator_create_empty(); } - - e = malloc_thing(attribute_enumerator_t); - e->public.enumerate = (void*)attribute_enumerate; - e->public.destroy = (void*)free; - e->next = (rattr_t*)this->msg->attributes; - e->left = ntohs(this->msg->length) - sizeof(rmsg_t); + INIT(e, + .public = { + .enumerate = (void*)_attribute_enumerate, + .destroy = (void*)free, + }, + .next = (rattr_t*)this->msg->attributes, + .left = ntohs(this->msg->length) - sizeof(rmsg_t), + ); return &e->public; } -/** - * Implementation of radius_message_t.add - */ -static void add(private_radius_message_t *this, radius_attribute_type_t type, - chunk_t data) +METHOD(radius_message_t, add, void, + private_radius_message_t *this, radius_attribute_type_t type, chunk_t data) { rattr_t *attribute; @@ -279,10 +271,8 @@ static void add(private_radius_message_t *this, radius_attribute_type_t type, this->msg->length = htons(ntohs(this->msg->length) + attribute->length); } -/** - * Implementation of radius_message_t.sign - */ -static void sign(private_radius_message_t *this, rng_t *rng, signer_t *signer) +METHOD(radius_message_t, sign, void, + private_radius_message_t *this, rng_t *rng, signer_t *signer) { char buf[HASH_SIZE_MD5]; @@ -297,11 +287,9 @@ static void sign(private_radius_message_t *this, rng_t *rng, signer_t *signer) ((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5); } -/** - * Implementation of radius_message_t.verify - */ -static bool verify(private_radius_message_t *this, u_int8_t *req_auth, - chunk_t secret, hasher_t *hasher, signer_t *signer) +METHOD(radius_message_t, verify, bool, + private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret, + hasher_t *hasher, signer_t *signer) { char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5]; enumerator_t *enumerator; @@ -369,51 +357,39 @@ static bool verify(private_radius_message_t *this, u_int8_t *req_auth, return TRUE; } -/** - * Implementation of radius_message_t.get_code - */ -static radius_message_code_t get_code(private_radius_message_t *this) +METHOD(radius_message_t, get_code, radius_message_code_t, + private_radius_message_t *this) { return this->msg->code; } -/** - * Implementation of radius_message_t.get_identifier - */ -static u_int8_t get_identifier(private_radius_message_t *this) +METHOD(radius_message_t, get_identifier, u_int8_t, + private_radius_message_t *this) { return this->msg->identifier; } -/** - * Implementation of radius_message_t.set_identifier - */ -static void set_identifier(private_radius_message_t *this, u_int8_t identifier) +METHOD(radius_message_t, set_identifier, void, + private_radius_message_t *this, u_int8_t identifier) { this->msg->identifier = identifier; } -/** - * Implementation of radius_message_t.get_authenticator - */ -static u_int8_t* get_authenticator(private_radius_message_t *this) +METHOD(radius_message_t, get_authenticator, u_int8_t*, + private_radius_message_t *this) { return this->msg->authenticator; } -/** - * Implementation of radius_message_t.get_encoding - */ -static chunk_t get_encoding(private_radius_message_t *this) +METHOD(radius_message_t, get_encoding, chunk_t, + private_radius_message_t *this) { return chunk_create((u_char*)this->msg, ntohs(this->msg->length)); } -/** - * Implementation of radius_message_t.destroy. - */ -static void destroy(private_radius_message_t *this) +METHOD(radius_message_t, destroy, void, + private_radius_message_t *this) { free(this->msg); free(this); @@ -424,18 +400,22 @@ static void destroy(private_radius_message_t *this) */ static private_radius_message_t *radius_message_create() { - private_radius_message_t *this = malloc_thing(private_radius_message_t); - - this->public.create_enumerator = (enumerator_t*(*)(radius_message_t*))create_enumerator; - this->public.add = (void(*)(radius_message_t*, radius_attribute_type_t,chunk_t))add; - this->public.get_code = (radius_message_code_t(*)(radius_message_t*))get_code; - this->public.get_identifier = (u_int8_t(*)(radius_message_t*))get_identifier; - this->public.set_identifier = (void(*)(radius_message_t*, u_int8_t identifier))set_identifier; - this->public.get_authenticator = (u_int8_t*(*)(radius_message_t*))get_authenticator; - this->public.get_encoding = (chunk_t(*)(radius_message_t*))get_encoding; - this->public.sign = (void(*)(radius_message_t*, rng_t *rng, signer_t *signer))sign; - this->public.verify = (bool(*)(radius_message_t*, u_int8_t *req_auth, chunk_t secret, hasher_t *hasher, signer_t *signer))verify; - this->public.destroy = (void(*)(radius_message_t*))destroy; + private_radius_message_t *this; + + INIT(this, + .public = { + .create_enumerator = _create_enumerator, + .add = _add, + .get_code = _get_code, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .get_authenticator = _get_authenticator, + .get_encoding = _get_encoding, + .sign = _sign, + .verify = _verify, + .destroy = _destroy, + }, + ); return this; } @@ -447,10 +427,11 @@ radius_message_t *radius_message_create_request() { private_radius_message_t *this = radius_message_create(); - this->msg = malloc_thing(rmsg_t); - this->msg->code = RMC_ACCESS_REQUEST; - this->msg->identifier = 0; - this->msg->length = htons(sizeof(rmsg_t)); + INIT(this->msg, + .code = RMC_ACCESS_REQUEST, + .identifier = 0, + .length = htons(sizeof(rmsg_t)), + ); return &this->public; } diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c new file mode 100644 index 000000000..f54b8b2cd --- /dev/null +++ b/src/libcharon/plugins/eap_radius/radius_server.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "radius_server.h" + +#include <threading/mutex.h> +#include <threading/condvar.h> +#include <utils/linked_list.h> + +typedef struct private_radius_server_t private_radius_server_t; + +/** + * Private data of an radius_server_t object. + */ +struct private_radius_server_t { + + /** + * Public radius_server_t interface. + */ + radius_server_t public; + + /** + * RADIUS server address + */ + host_t *host; + + /** + * list of radius sockets, as radius_socket_t + */ + linked_list_t *sockets; + + /** + * Total number of sockets, in list + currently in use + */ + int socket_count; + + /** + * mutex to lock sockets list + */ + mutex_t *mutex; + + /** + * condvar to wait for sockets + */ + condvar_t *condvar; + + /** + * RADIUS secret + */ + chunk_t secret; + + /** + * NAS-Identifier + */ + chunk_t nas_identifier; + + /** + * Preference boost for this server + */ + int preference; + + /** + * Is the server currently reachable + */ + bool reachable; + + /** + * Retry counter for unreachable servers + */ + int retry; +}; + +METHOD(radius_server_t, get_socket, radius_socket_t*, + private_radius_server_t *this) +{ + radius_socket_t *skt; + + this->mutex->lock(this->mutex); + while (this->sockets->remove_first(this->sockets, (void**)&skt) != SUCCESS) + { + this->condvar->wait(this->condvar, this->mutex); + } + this->mutex->unlock(this->mutex); + return skt; +} + +METHOD(radius_server_t, put_socket, void, + private_radius_server_t *this, radius_socket_t *skt, bool result) +{ + this->mutex->lock(this->mutex); + this->sockets->insert_last(this->sockets, skt); + this->mutex->unlock(this->mutex); + this->condvar->signal(this->condvar); + this->reachable = result; +} + +METHOD(radius_server_t, get_nas_identifier, chunk_t, + private_radius_server_t *this) +{ + return this->nas_identifier; +} + +METHOD(radius_server_t, get_preference, int, + private_radius_server_t *this) +{ + int pref; + + if (this->socket_count == 0) + { /* don't have sockets, huh? */ + return -1; + } + /* calculate preference between 0-100 + boost */ + pref = this->preference; + pref += this->sockets->get_count(this->sockets) * 100 / this->socket_count; + if (this->reachable) + { /* reachable server get a boost: pref = 110-210 + boost */ + return pref + 110; + } + /* Not reachable. Increase preference randomly to let it retry from + * time to time, especially if other servers have high load. */ + this->retry++; + if (this->retry % 128 == 0) + { /* every 64th request gets 210, same as unloaded reachable */ + return pref + 110; + } + if (this->retry % 32 == 0) + { /* every 32th request gets 190, wins against average loaded */ + return pref + 90; + } + if (this->retry % 8 == 0) + { /* every 8th request gets 110, same as server under load */ + return pref + 10; + } + /* other get ~100, less than fully loaded */ + return pref; +} + +METHOD(radius_server_t, get_address, host_t*, + private_radius_server_t *this) +{ + return this->host; +} + +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); +} + +/** + * See header + */ +radius_server_t *radius_server_create(char *server, u_int16_t port, + char *nas_identifier, char *secret, int sockets, int preference) +{ + private_radius_server_t *this; + radius_socket_t *socket; + + INIT(this, + .public = { + .get_socket = _get_socket, + .put_socket = _put_socket, + .get_nas_identifier = _get_nas_identifier, + .get_preference = _get_preference, + .get_address = _get_address, + .destroy = _destroy, + }, + .reachable = TRUE, + .nas_identifier = chunk_create(nas_identifier, strlen(nas_identifier)), + .socket_count = sockets, + .sockets = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .host = host_create_from_dns(server, 0, port), + .preference = preference, + ); + + if (!this->host) + { + destroy(this); + return NULL; + } + while (sockets--) + { + socket = radius_socket_create(this->host, + chunk_create(secret, strlen(secret))); + if (!socket) + { + destroy(this); + return NULL; + } + this->sockets->insert_last(this->sockets, socket); + } + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h new file mode 100644 index 000000000..b820cb583 --- /dev/null +++ b/src/libcharon/plugins/eap_radius/radius_server.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup radius_server radius_server + * @{ @ingroup eap_radius + */ + +#ifndef RADIUS_SERVER_H_ +#define RADIUS_SERVER_H_ + +typedef struct radius_server_t radius_server_t; + +#include "radius_socket.h" + +/** + * RADIUS server configuration. + */ +struct radius_server_t { + + /** + * Get a RADIUS socket from the pool to communicate with this server. + * + * @return RADIUS socket + */ + radius_socket_t* (*get_socket)(radius_server_t *this); + + /** + * Release a socket to the pool after use. + * + * @param skt RADIUS socket to release + * @param result result of the socket use, TRUE for success + */ + void (*put_socket)(radius_server_t *this, radius_socket_t *skt, bool result); + + /** + * Get the NAS-Identifier to use with this server. + * + * @return NAS-Identifier, internal data + */ + chunk_t (*get_nas_identifier)(radius_server_t *this); + + /** + * Get the preference of this server. + * + * Based on the available sockets and the server reachability a preference + * value is calculated: better servers return a higher value. + */ + int (*get_preference)(radius_server_t *this); + + /** + * Get the address of the RADIUS server. + * + * @return address, internal data + */ + host_t* (*get_address)(radius_server_t *this); + + /** + * Destroy a radius_server_t. + */ + void (*destroy)(radius_server_t *this); +}; + +/** + * Create a radius_server instance. + * + * @param server server address + * @param port server port + * @param nas_identifier NAS-Identifier 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, + 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 new file mode 100644 index 000000000..f46c27ede --- /dev/null +++ b/src/libcharon/plugins/eap_radius/radius_socket.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "radius_socket.h" + +#include <errno.h> +#include <unistd.h> + +#include <debug.h> + +/** + * Vendor-Id of Microsoft specific attributes + */ +#define VENDOR_ID_MICROSOFT 311 + +/** + * Microsoft specific vendor attributes + */ +#define MS_MPPE_SEND_KEY 16 +#define MS_MPPE_RECV_KEY 17 + +typedef struct private_radius_socket_t private_radius_socket_t; + +/** + * Private data of an radius_socket_t object. + */ +struct private_radius_socket_t { + + /** + * Public radius_socket_t interface. + */ + radius_socket_t public; + + /** + * socket file descriptor + */ + int fd; + + /** + * current RADIUS identifier + */ + u_int8_t identifier; + + /** + * hasher to use for response verification + */ + hasher_t *hasher; + + /** + * HMAC-MD5 signer to build Message-Authenticator attribute + */ + signer_t *signer; + + /** + * random number generator for RADIUS request authenticator + */ + rng_t *rng; + + /** + * RADIUS secret + */ + chunk_t secret; +}; + +METHOD(radius_socket_t, request, radius_message_t*, + private_radius_socket_t *this, radius_message_t *request) +{ + chunk_t data; + int i; + + /* set Message Identifier */ + request->set_identifier(request, this->identifier++); + /* sign the request */ + request->sign(request, this->rng, this->signer); + + data = request->get_encoding(request); + /* timeout after 2, 3, 4, 5 seconds */ + for (i = 2; i <= 5; i++) + { + radius_message_t *response; + bool retransmit = FALSE; + struct timeval tv; + char buf[4096]; + fd_set fds; + int res; + + if (send(this->fd, data.ptr, data.len, 0) != data.len) + { + DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno)); + return NULL; + } + tv.tv_sec = i; + tv.tv_usec = 0; + + while (TRUE) + { + FD_ZERO(&fds); + FD_SET(this->fd, &fds); + res = select(this->fd + 1, &fds, NULL, NULL, &tv); + /* TODO: updated tv to time not waited. Linux does this for us. */ + if (res < 0) + { /* failed */ + DBG1(DBG_CFG, "waiting for RADIUS message failed: %s", + strerror(errno)); + break; + } + if (res == 0) + { /* timeout */ + DBG1(DBG_CFG, "retransmitting RADIUS message"); + retransmit = TRUE; + break; + } + res = recv(this->fd, buf, sizeof(buf), MSG_DONTWAIT); + if (res <= 0) + { + DBG1(DBG_CFG, "receiving RADIUS message failed: %s", + strerror(errno)); + break; + } + response = radius_message_parse_response(chunk_create(buf, res)); + if (response) + { + if (response->verify(response, + request->get_authenticator(request), this->secret, + this->hasher, this->signer)) + { + return response; + } + response->destroy(response); + } + DBG1(DBG_CFG, "received invalid RADIUS message, ignored"); + } + if (!retransmit) + { + break; + } + } + DBG1(DBG_CFG, "RADIUS server is not responding"); + return NULL; +} + +/** + * Decrypt a MS-MPPE-Send/Recv-Key + */ +static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt, + chunk_t C, radius_message_t *request) +{ + chunk_t A, R, P, seed; + u_char *c, *p; + + /** + * From RFC2548 (encryption): + * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1) + * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2) + * . . . + * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i) + */ + + if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5) + { + return chunk_empty; + } + + A = chunk_create((u_char*)&salt, sizeof(salt)); + R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5); + P = chunk_alloca(C.len); + p = P.ptr; + c = C.ptr; + + seed = chunk_cata("cc", R, A); + + while (c < C.ptr + C.len) + { + /* b(i) = MD5(S + c(i-1)) */ + this->hasher->get_hash(this->hasher, this->secret, NULL); + this->hasher->get_hash(this->hasher, seed, p); + + /* p(i) = b(i) xor c(1) */ + memxor(p, c, HASH_SIZE_MD5); + + /* prepare next round */ + seed = chunk_create(c, HASH_SIZE_MD5); + c += HASH_SIZE_MD5; + p += HASH_SIZE_MD5; + } + + /* remove truncation, first byte is key length */ + if (*P.ptr >= P.len) + { /* decryption failed? */ + return chunk_empty; + } + return chunk_clone(chunk_create(P.ptr + 1, *P.ptr)); +} + +METHOD(radius_socket_t, decrypt_msk, chunk_t, + private_radius_socket_t *this, radius_message_t *request, + radius_message_t *response) +{ + struct { + u_int32_t id; + u_int8_t type; + u_int8_t length; + u_int16_t salt; + u_int8_t key[]; + } __attribute__((packed)) *mppe_key; + enumerator_t *enumerator; + chunk_t data, send = chunk_empty, recv = chunk_empty; + int type; + + enumerator = response->create_enumerator(response); + while (enumerator->enumerate(enumerator, &type, &data)) + { + if (type == RAT_VENDOR_SPECIFIC && + data.len > sizeof(*mppe_key)) + { + mppe_key = (void*)data.ptr; + if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT && + mppe_key->length == data.len - sizeof(mppe_key->id)) + { + data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key)); + if (mppe_key->type == MS_MPPE_SEND_KEY) + { + send = decrypt_mppe_key(this, mppe_key->salt, data, request); + } + if (mppe_key->type == MS_MPPE_RECV_KEY) + { + recv = decrypt_mppe_key(this, mppe_key->salt, data, request); + } + } + } + } + enumerator->destroy(enumerator); + if (send.ptr && recv.ptr) + { + return chunk_cat("mm", recv, send); + } + chunk_clear(&send); + chunk_clear(&recv); + return chunk_empty; +} + +METHOD(radius_socket_t, destroy, void, + private_radius_socket_t *this) +{ + DESTROY_IF(this->hasher); + DESTROY_IF(this->signer); + DESTROY_IF(this->rng); + close(this->fd); + free(this); +} + +/** + * See header + */ +radius_socket_t *radius_socket_create(host_t *host, chunk_t secret) +{ + private_radius_socket_t *this; + + INIT(this, + .public = { + .request = _request, + .decrypt_msk = _decrypt_msk, + .destroy = _destroy, + }, + ); + + 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); + if (!this->hasher || !this->signer || !this->rng) + { + DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required"); + destroy(this); + return NULL; + } + this->secret = secret; + this->signer->set_key(this->signer, secret); + /* we use a random identifier, helps if we restart often */ + this->identifier = random(); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h new file mode 100644 index 000000000..fe8491a8f --- /dev/null +++ b/src/libcharon/plugins/eap_radius/radius_socket.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup radius_socket radius_socket + * @{ @ingroup eap_radius + */ + +#ifndef RADIUS_SOCKET_H_ +#define RADIUS_SOCKET_H_ + +typedef struct radius_socket_t radius_socket_t; + +#include "radius_message.h" + +#include <utils/host.h> + +/** + * RADIUS socket to a server. + */ +struct radius_socket_t { + + /** + * Send a RADIUS request, wait for response. + + * The socket fills in RADIUS Message identifier, builds a + * Request-Authenticator and calculates the Message-Authenticator + * attribute. + * The received response gets verified using the Response-Identifier + * and the Message-Authenticator attribute. + * + * @param request request message + * @return response message, NULL if timed out + */ + radius_message_t* (*request)(radius_socket_t *this, + radius_message_t *request); + + /** + * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key. + * + * @param request associated RADIUS request message + * @param response RADIUS response message containing attributes + * @return allocated MSK, empty chunk if none found + */ + chunk_t (*decrypt_msk)(radius_socket_t *this, radius_message_t *request, + radius_message_t *response); + + /** + * Destroy a radius_socket_t. + */ + void (*destroy)(radius_socket_t *this); +}; + +/** + * Create a radius_socket instance. + * + * @param host RADIUS server address to connect to + * @param secret RADIUS secret + */ +radius_socket_t *radius_socket_create(host_t *host, 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 588965113..d0f44e925 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c index 961cfd30d..a3506f4ba 100644 --- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c +++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c @@ -484,7 +484,6 @@ static status_t process_notification(private_eap_sim_peer_t *this, /* test success bit */ if (!(data.ptr[0] & 0x80)) { - success = FALSE; DBG1(DBG_IKE, "received EAP-SIM notification error '%N'", simaka_notification_names, code); } diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index 2d998dbcc..2aa0ac832 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index 6c44ea2bb..7d80f8019 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index 35d8e7c3b..fc26f4497 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am new file mode 100644 index 000000000..73768be0e --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/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 -DIPSEC_CONFDIR=\"${sysconfdir}\" + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +else +plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +endif + +libstrongswan_eap_simaka_sql_la_SOURCES = \ + eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \ + eap_simaka_sql_card.h eap_simaka_sql_card.c \ + eap_simaka_sql_provider.h eap_simaka_sql_provider.c + +libstrongswan_eap_simaka_sql_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in new file mode 100644 index 000000000..f2e82df0a --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -0,0 +1,592 @@ +# 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_simaka_sql +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)/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_eap_simaka_sql_la_LIBADD = +am_libstrongswan_eap_simaka_sql_la_OBJECTS = eap_simaka_sql_plugin.lo \ + eap_simaka_sql_card.lo eap_simaka_sql_provider.lo +libstrongswan_eap_simaka_sql_la_OBJECTS = \ + $(am_libstrongswan_eap_simaka_sql_la_OBJECTS) +libstrongswan_eap_simaka_sql_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libstrongswan_eap_simaka_sql_la_LDFLAGS) $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_sql_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_sql_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_simaka_sql_la_SOURCES) +DIST_SOURCES = $(libstrongswan_eap_simaka_sql_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@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +default_pkcs11 = @default_pkcs11@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +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@ +ipsecgid = @ipsecgid@ +ipsecgroup = @ipsecgroup@ +ipsecuid = @ipsecuid@ +ipsecuser = @ipsecuser@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libhydra_plugins = @libhydra_plugins@ +libstrongswan_plugins = @libstrongswan_plugins@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +piddir = @piddir@ +plugindir = @plugindir@ +pluto_plugins = @pluto_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@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +strongswan_conf = @strongswan_conf@ +sysconfdir = @sysconfdir@ +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_CONFDIR=\"${sysconfdir}\" +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la +libstrongswan_eap_simaka_sql_la_SOURCES = \ + eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \ + eap_simaka_sql_card.h eap_simaka_sql_card.c \ + eap_simaka_sql_provider.h eap_simaka_sql_provider.c + +libstrongswan_eap_simaka_sql_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_simaka_sql/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_sql/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-simaka-sql.la: $(libstrongswan_eap_simaka_sql_la_OBJECTS) $(libstrongswan_eap_simaka_sql_la_DEPENDENCIES) + $(libstrongswan_eap_simaka_sql_la_LINK) $(am_libstrongswan_eap_simaka_sql_la_rpath) $(libstrongswan_eap_simaka_sql_la_OBJECTS) $(libstrongswan_eap_simaka_sql_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_card.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_provider.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_simaka_sql/eap_simaka_sql_card.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c new file mode 100644 index 000000000..b7590405f --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_simaka_sql_card.h" + +#include <time.h> + +#include <daemon.h> + +typedef struct private_eap_simaka_sql_card_t private_eap_simaka_sql_card_t; + +/** + * Private data of an eap_simaka_sql_card_t object. + */ +struct private_eap_simaka_sql_card_t { + + /** + * Public eap_simaka_sql_card_t interface. + */ + eap_simaka_sql_card_t public; + + /** + * Triplet/quintuplet database + */ + database_t *db; + + /** + * Remove used triplets/quintuplets from database + */ + bool remove_used; +}; + +METHOD(sim_card_t, get_triplet, bool, + private_eap_simaka_sql_card_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) +{ + chunk_t sres_chunk, kc_chunk; + enumerator_t *query; + bool found = FALSE; + char buf[128]; + + snprintf(buf, sizeof(buf), "%Y", id); + query = this->db->query(this->db, + "select sres, kc from triplets where rand = ? and id = ? " + "order by use limit 1", + DB_BLOB, chunk_create(rand, SIM_RAND_LEN), DB_TEXT, buf, + DB_BLOB, DB_BLOB); + if (query) + { + if (query->enumerate(query, &sres_chunk, &kc_chunk)) + { + if (sres_chunk.len == SIM_SRES_LEN && + kc_chunk.len == SIM_KC_LEN) + { + memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN); + memcpy(kc, kc_chunk.ptr, SIM_KC_LEN); + found = TRUE; + } + } + query->destroy(query); + } + if (found) + { + if (this->remove_used) + { + this->db->execute(this->db, NULL, + "delete from triplets where id = ? and rand = ?", + DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + else + { + this->db->execute(this->db, NULL, + "update triplets set use = ? where id = ? and rand = ?", + DB_UINT, time(NULL), DB_TEXT, buf, + DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + } + return found; +} + +METHOD(sim_card_t, get_quintuplet, status_t, + private_eap_simaka_sql_card_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], + char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) +{ + chunk_t ck_chunk, ik_chunk, res_chunk; + enumerator_t *query; + status_t found = FAILED; + char buf[128]; + + snprintf(buf, sizeof(buf), "%Y", id); + query = this->db->query(this->db, "select ck, ik, res from quintuplets " + "where rand = ? and autn = ? and id = ? order by use limit 1", + DB_BLOB, chunk_create(rand, AKA_RAND_LEN), + DB_BLOB, chunk_create(autn, AKA_AUTN_LEN), DB_TEXT, buf, + DB_BLOB, DB_BLOB, DB_BLOB); + if (query) + { + if (query->enumerate(query, &ck_chunk, &ik_chunk, &res_chunk)) + { + if (ck_chunk.len == AKA_CK_LEN && + ik_chunk.len == AKA_IK_LEN && + res_chunk.len <= AKA_RES_MAX) + { + memcpy(ck, ck_chunk.ptr, AKA_CK_LEN); + memcpy(ik, ik_chunk.ptr, AKA_IK_LEN); + memcpy(res, res_chunk.ptr, res_chunk.len); + *res_len = res_chunk.len; + found = SUCCESS; + } + } + query->destroy(query); + } + if (found == SUCCESS) + { + if (this->remove_used) + { + this->db->execute(this->db, NULL, + "delete from quintuplets where id = ? and rand = ?", + DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + else + { + this->db->execute(this->db, NULL, + "update quintuplets set use = ? where id = ? and rand = ?", + DB_UINT, time(NULL), DB_TEXT, buf, + DB_BLOB, chunk_create(rand, AKA_RAND_LEN)); + } + } + return found; +} + +METHOD(eap_simaka_sql_card_t, destroy, void, + private_eap_simaka_sql_card_t *this) +{ + free(this); +} + +/** + * See header + */ +eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db, + bool remove_used) +{ + private_eap_simaka_sql_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, + }, + .db = db, + .remove_used = remove_used, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h new file mode 100644 index 000000000..46b7de25e --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_simaka_sql_card eap_simaka_sql_card + * @{ @ingroup eap_simaka_sql + */ + +#ifndef EAP_SIMAKA_SQL_CARD_H_ +#define EAP_SIMAKA_SQL_CARD_H_ + +#include <database/database.h> +#include <sa/authenticators/eap/sim_manager.h> + +typedef struct eap_simaka_sql_card_t eap_simaka_sql_card_t; + +/** + * SIM card implementation using a triplet/quintuplet database backend. + */ +struct eap_simaka_sql_card_t { + + /** + * Implements sim_card_t interface + */ + sim_card_t card; + + /** + * Destroy a eap_simaka_sql_card_t. + */ + void (*destroy)(eap_simaka_sql_card_t *this); +}; + +/** + * Create a eap_simaka_sql_card instance. + * + * @param db triplet/quintuplet database + * @param remove_used TRUE to remove used triplets/quintuplets from db + */ +eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db, + bool remove_used); + +#endif /** EAP_SIMAKA_SQL_CARD_H_ @}*/ 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 new file mode 100644 index 000000000..0f5319792 --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_simaka_sql_plugin.h" +#include "eap_simaka_sql_card.h" +#include "eap_simaka_sql_provider.h" + +#include <daemon.h> + +typedef struct private_eap_simaka_sql_t private_eap_simaka_sql_t; + +/** + * Private data of an eap_simaka_sql_t object. + */ +struct private_eap_simaka_sql_t { + + /** + * Public eap_simaka_sql_plugin_t interface. + */ + eap_simaka_sql_plugin_t public; + + /** + * (U)SIM card + */ + eap_simaka_sql_card_t *card; + + /** + * (U)SIM provider + */ + eap_simaka_sql_provider_t *provider; + + /** + * Database with triplets/quintuplets + */ + database_t *db; +}; + +METHOD(plugin_t, destroy, void, + private_eap_simaka_sql_t *this) +{ + charon->sim->remove_card(charon->sim, &this->card->card); + charon->sim->remove_provider(charon->sim, &this->provider->provider); + this->card->destroy(this->card); + this->provider->destroy(this->provider); + this->db->destroy(this->db); + free(this); +} + +/** + * See header + */ +plugin_t *eap_simaka_sql_plugin_create() +{ + private_eap_simaka_sql_t *this; + database_t *db; + bool remove_used; + char *uri; + + uri = lib->settings->get_str(lib->settings, + "charon.plugins.eap-simaka-sql.database", NULL); + if (!uri) + { + DBG1(DBG_CFG, "eap-simaka-sql database URI missing"); + return NULL; + } + db = lib->db->create(lib->db, uri); + if (!db) + { + DBG1(DBG_CFG, "opening eap-simaka-sql database failed"); + return NULL; + } + remove_used = lib->settings->get_bool(lib->settings, + "charon.plugins.eap-simaka-sql.remove_used", FALSE); + + INIT(this, + .public.plugin = { + .destroy = _destroy, + }, + .db = db, + .provider = eap_simaka_sql_provider_create(db, remove_used), + .card = eap_simaka_sql_card_create(db, remove_used), + ); + + charon->sim->add_card(charon->sim, &this->card->card); + charon->sim->add_provider(charon->sim, &this->provider->provider); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h new file mode 100644 index 000000000..3064580bf --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_simaka_sql eap_simaka_sql + * @ingroup cplugins + * + * @defgroup eap_simaka_sql_plugin eap_simaka_sql_plugin + * @{ @ingroup eap_simaka_sql + */ + +#ifndef EAP_SIMAKA_SQL_PLUGIN_H_ +#define EAP_SIMAKA_SQL_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct eap_simaka_sql_plugin_t eap_simaka_sql_plugin_t; + +/** + * Plugin to provide SIM/AKA cards/providers using triplets from a database. + */ +struct eap_simaka_sql_plugin_t { + + /** + * Implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** EAP_SIMAKA_SQL_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c new file mode 100644 index 000000000..73cccf549 --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "eap_simaka_sql_provider.h" + +#include <time.h> + +#include <daemon.h> + +typedef struct private_eap_simaka_sql_provider_t private_eap_simaka_sql_provider_t; + +/** + * Private data of an eap_simaka_sql_provider_t object. + */ +struct private_eap_simaka_sql_provider_t { + + /** + * Public eap_simaka_sql_provider_t interface. + */ + eap_simaka_sql_provider_t public; + + /** + * Triplet/quintuplet database + */ + database_t *db; + + /** + * Remove used triplets/quintuplets from database + */ + bool remove_used; +}; + +METHOD(sim_provider_t, get_triplet, bool, + private_eap_simaka_sql_provider_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) +{ + chunk_t rand_chunk, sres_chunk, kc_chunk; + enumerator_t *query; + bool found = FALSE; + char buf[128]; + + snprintf(buf, sizeof(buf), "%Y", id); + query = this->db->query(this->db, + "select rand, sres, kc from triplets where id = ? order by use", + DB_TEXT, buf, DB_BLOB, DB_BLOB, DB_BLOB); + if (query) + { + if (query->enumerate(query, &rand_chunk, &sres_chunk, &kc_chunk)) + { + if (rand_chunk.len == SIM_RAND_LEN && + sres_chunk.len == SIM_SRES_LEN && + kc_chunk.len == SIM_KC_LEN) + { + memcpy(rand, rand_chunk.ptr, SIM_RAND_LEN); + memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN); + memcpy(kc, kc_chunk.ptr, SIM_KC_LEN); + found = TRUE; + } + } + query->destroy(query); + } + if (found) + { + if (this->remove_used) + { + this->db->execute(this->db, NULL, + "delete from triplets where id = ? and rand = ?", + DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + else + { + this->db->execute(this->db, NULL, + "update triplets set use = ? where id = ? and rand = ?", + DB_UINT, time(NULL), DB_TEXT, buf, + DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + } + return found; +} + +METHOD(sim_provider_t, get_quintuplet, bool, + private_eap_simaka_sql_provider_t *this, identification_t *id, + char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len, + char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]) +{ + chunk_t rand_chunk, xres_chunk, ck_chunk, ik_chunk, autn_chunk; + enumerator_t *query; + bool found = FALSE; + char buf[128]; + + snprintf(buf, sizeof(buf), "%Y", id); + query = this->db->query(this->db, "select rand, res, ck, ik, autn " + "from quintuplets where id = ? order by use", DB_TEXT, buf, + DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB); + if (query) + { + if (query->enumerate(query, &rand_chunk, &xres_chunk, + &ck_chunk, &ik_chunk, &autn_chunk)) + { + if (rand_chunk.len == AKA_RAND_LEN && + xres_chunk.len <= AKA_RES_MAX && + ck_chunk.len == AKA_CK_LEN && + ik_chunk.len == AKA_IK_LEN && + autn_chunk.len == AKA_AUTN_LEN) + { + memcpy(rand, rand_chunk.ptr, AKA_RAND_LEN); + memcpy(xres, xres_chunk.ptr, xres_chunk.len); + *xres_len = xres_chunk.len; + memcpy(ck, ck_chunk.ptr, AKA_CK_LEN); + memcpy(ik, ik_chunk.ptr, AKA_IK_LEN); + memcpy(autn, autn_chunk.ptr, AKA_AUTN_LEN); + found = TRUE; + } + } + query->destroy(query); + } + if (found) + { + if (this->remove_used) + { + this->db->execute(this->db, NULL, + "delete from quintuplets where id = ? and rand = ?", + DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN)); + } + else + { + this->db->execute(this->db, NULL, + "update quintuplets set use = ? where id = ? and rand = ?", + DB_UINT, time(NULL), DB_TEXT, buf, + DB_BLOB, chunk_create(rand, AKA_RAND_LEN)); + } + } + return found; +} + +METHOD(eap_simaka_sql_provider_t, destroy, void, + private_eap_simaka_sql_provider_t *this) +{ + free(this); +} + +/** + * See header + */ +eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db, + bool remove_used) +{ + private_eap_simaka_sql_provider_t *this; + + INIT(this, + .public = { + .provider = { + .get_triplet = _get_triplet, + .get_quintuplet = _get_quintuplet, + .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, + }, + .db = db, + .remove_used = remove_used, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h new file mode 100644 index 000000000..ecb0c8cb0 --- /dev/null +++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup eap_simaka_sql_provider eap_simaka_sql_provider + * @{ @ingroup eap_simaka_sql + */ + +#ifndef EAP_SIMAKA_SQL_PROVIDER_H_ +#define EAP_SIMAKA_SQL_PROVIDER_H_ + +#include <database/database.h> +#include <sa/authenticators/eap/sim_manager.h> + +typedef struct eap_simaka_sql_provider_t eap_simaka_sql_provider_t; + +/** + * SIM provider implementation using a triplet/quintuplet database backend. + */ +struct eap_simaka_sql_provider_t { + + /** + * Implements sim_provider_t interface + */ + sim_provider_t provider; + + /** + * Destroy a eap_simaka_sql_provider_t. + */ + void (*destroy)(eap_simaka_sql_provider_t *this); +}; + +/** + * Create a eap_simaka_sql_provider instance. + * + * @param db triplet/quintuplet database + * @param remove_used TRUE to remove used triplets/quintuplets from db + */ +eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db, + bool remove_used); + +#endif /** EAP_SIMAKA_SQL_PROVIDER_H_ @}*/ diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index 20ac77080..47952b99e 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c index 29e64e32d..20bb44fd3 100644 --- a/src/libcharon/plugins/farp/farp_spoofer.c +++ b/src/libcharon/plugins/farp/farp_spoofer.c @@ -156,8 +156,8 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener) BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3), BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 28, 0, 1), - BPF_STMT(BPF_RET+BPF_A, 0), + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, sizeof(arp_t), 0, 1), + BPF_STMT(BPF_RET+BPF_K, sizeof(arp_t)), BPF_STMT(BPF_RET+BPF_K, 0), }; struct sock_fprog arp_request_filter = { diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am index 74fe1f4c7..0df1b8d91 100644 --- a/src/libcharon/plugins/ha/Makefile.am +++ b/src/libcharon/plugins/ha/Makefile.am @@ -17,9 +17,11 @@ libstrongswan_ha_la_SOURCES = \ ha_tunnel.h ha_tunnel.c \ ha_dispatcher.h ha_dispatcher.c \ ha_segments.h ha_segments.c \ + ha_cache.h ha_cache.c \ ha_kernel.h ha_kernel.c \ ha_ctl.h ha_ctl.c \ ha_ike.h ha_ike.c \ - ha_child.h ha_child.c + ha_child.h ha_child.c \ + ha_attribute.h ha_attribute.c libstrongswan_ha_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index c60d3bf56..5ca9b464b 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -76,7 +76,8 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) libstrongswan_ha_la_LIBADD = am_libstrongswan_ha_la_OBJECTS = ha_plugin.lo ha_message.lo \ ha_socket.lo ha_tunnel.lo ha_dispatcher.lo ha_segments.lo \ - ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo + ha_cache.lo ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo \ + ha_attribute.lo libstrongswan_ha_la_OBJECTS = $(am_libstrongswan_ha_la_OBJECTS) libstrongswan_ha_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -269,10 +270,12 @@ libstrongswan_ha_la_SOURCES = \ ha_tunnel.h ha_tunnel.c \ ha_dispatcher.h ha_dispatcher.c \ ha_segments.h ha_segments.c \ + ha_cache.h ha_cache.c \ ha_kernel.h ha_kernel.c \ ha_ctl.h ha_ctl.c \ ha_ike.h ha_ike.c \ - ha_child.h ha_child.c + ha_child.h ha_child.c \ + ha_attribute.h ha_attribute.c libstrongswan_ha_la_LDFLAGS = -module -avoid-version all: all-am @@ -358,6 +361,8 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_attribute.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_child.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_ctl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_dispatcher.Plo@am__quote@ diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c new file mode 100644 index 000000000..b08abe1a9 --- /dev/null +++ b/src/libcharon/plugins/ha/ha_attribute.c @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ha_attribute.h" + +#include <utils/linked_list.h> +#include <threading/mutex.h> + +typedef struct private_ha_attribute_t private_ha_attribute_t; + +/** + * Private data of an ha_attribute_t object. + */ +struct private_ha_attribute_t { + + /** + * Public ha_attribute_t interface. + */ + ha_attribute_t public; + + /** + * List of pools, pool_t + */ + linked_list_t *pools; + + /** + * Mutex to lock mask + */ + mutex_t *mutex; + + /** + * Kernel helper + */ + ha_kernel_t *kernel; + + /** + * Segment responsibility + */ + ha_segments_t *segments; +}; + +/** + * In-memory pool. + */ +typedef struct { + /** name of the pool */ + char *name; + /** base address of pool */ + host_t *base; + /** total number of addresses in this pool */ + int size; + /** bitmask for address usage */ + u_char *mask; +} pool_t; + +/** + * Clean up a pool entry + */ +static void pool_destroy(pool_t *pool) +{ + pool->base->destroy(pool->base); + free(pool->name); + free(pool->mask); + free(pool); +} + +/** + * convert a pool offset to an address + */ +static host_t* offset2host(pool_t *pool, int offset) +{ + chunk_t addr; + host_t *host; + u_int32_t *pos; + + if (offset > pool->size) + { + return NULL; + } + + addr = chunk_clone(pool->base->get_address(pool->base)); + if (pool->base->get_family(pool->base) == AF_INET6) + { + pos = (u_int32_t*)(addr.ptr + 12); + } + else + { + pos = (u_int32_t*)addr.ptr; + } + *pos = htonl(offset + ntohl(*pos)); + host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0); + free(addr.ptr); + return host; +} + +/** + * convert a host to a pool offset + */ +static int host2offset(pool_t *pool, host_t *addr) +{ + chunk_t host, base; + u_int32_t hosti, basei; + + if (addr->get_family(addr) != pool->base->get_family(pool->base)) + { + return -1; + } + host = addr->get_address(addr); + base = pool->base->get_address(pool->base); + if (addr->get_family(addr) == AF_INET6) + { + /* only look at last /32 block */ + if (!memeq(host.ptr, base.ptr, 12)) + { + return -1; + } + host = chunk_skip(host, 12); + base = chunk_skip(base, 12); + } + hosti = ntohl(*(u_int32_t*)(host.ptr)); + basei = ntohl(*(u_int32_t*)(base.ptr)); + if (hosti > basei + pool->size) + { + return -1; + } + return hosti - basei; +} + +/** + * Find a pool by its name + */ +static pool_t* get_pool(private_ha_attribute_t *this, char *name) +{ + enumerator_t *enumerator; + pool_t *pool, *found = NULL; + + enumerator = this->pools->create_enumerator(this->pools); + while (enumerator->enumerate(enumerator, &pool)) + { + if (streq(name, pool->name)) + { + found = pool; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * Check if we are responsible for a bit in our bitmask + */ +static bool responsible_for(private_ha_attribute_t *this, int bit) +{ + u_int segment; + + segment = this->kernel->get_segment_int(this->kernel, bit); + return this->segments->is_active(this->segments, segment); +} + +METHOD(attribute_provider_t, acquire_address, host_t*, + private_ha_attribute_t *this, char *name, identification_t *id, + host_t *requested) +{ + pool_t *pool; + int offset = -1, byte, bit; + host_t *address; + + this->mutex->lock(this->mutex); + pool = get_pool(this, name); + if (pool) + { + for (byte = 0; byte < pool->size / 8; byte++) + { + if (pool->mask[byte] != 0xFF) + { + for (bit = 0; bit < 8; bit++) + { + if (!(pool->mask[byte] & 1 << bit) && + responsible_for(this, bit)) + { + offset = byte * 8 + bit; + pool->mask[byte] |= 1 << bit; + break; + } + } + } + if (offset != -1) + { + break; + } + } + if (offset == -1) + { + DBG1(DBG_CFG, "no address left in HA pool '%s' belonging to" + "a responsible segment", name); + } + } + this->mutex->unlock(this->mutex); + if (offset != -1) + { + address = offset2host(pool, offset); + DBG1(DBG_CFG, "acquired address %H from HA pool '%s'", address, name); + return address; + } + return NULL; +} + +METHOD(attribute_provider_t, release_address, bool, + private_ha_attribute_t *this, char *name, host_t *address, + identification_t *id) +{ + pool_t *pool; + int offset; + bool found = FALSE; + + this->mutex->lock(this->mutex); + pool = get_pool(this, name); + if (pool) + { + offset = host2offset(pool, address); + if (offset > 0 && offset < pool->size) + { + pool->mask[offset / 8] &= ~(1 << (offset % 8)); + DBG1(DBG_CFG, "released address %H to HA pool '%s'", address, name); + found = TRUE; + } + } + this->mutex->unlock(this->mutex); + return found; +} + +METHOD(ha_attribute_t, reserve, void, + private_ha_attribute_t *this, char *name, host_t *address) +{ + pool_t *pool; + int offset; + + this->mutex->lock(this->mutex); + pool = get_pool(this, name); + if (pool) + { + offset = host2offset(pool, address); + if (offset > 0 && offset < pool->size) + { + pool->mask[offset / 8] |= 1 << (offset % 8); + DBG1(DBG_CFG, "reserved address %H in HA pool '%s'", address, name); + } + } + this->mutex->unlock(this->mutex); +} + +METHOD(ha_attribute_t, destroy, void, + private_ha_attribute_t *this) +{ + this->pools->destroy_function(this->pools, (void*)pool_destroy); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * Load the configured pools. + */ +static void load_pools(private_ha_attribute_t *this) +{ + enumerator_t *enumerator; + char *name, *net, *bits; + host_t *base; + int mask, maxbits; + pool_t *pool; + + enumerator = lib->settings->create_key_value_enumerator(lib->settings, + "charon.plugins.ha.pools"); + while (enumerator->enumerate(enumerator, &name, &net)) + { + net = strdup(net); + bits = strchr(net, '/'); + if (!bits) + { + DBG1(DBG_CFG, "invalid HA pool '%s' subnet, skipped", name); + free(net); + continue; + } + *bits++ = '\0'; + + base = host_create_from_string(net, 0); + mask = atoi(bits); + free(net); + if (!base || !mask) + { + DESTROY_IF(base); + DBG1(DBG_CFG, "invalid HA pool '%s', skipped", name); + continue; + } + maxbits = base->get_family(base) == AF_INET ? 32 : 128; + mask = maxbits - mask; + if (mask > 24) + { + mask = 24; + DBG1(DBG_CFG, "size of HA pool '%s' limited to /%d", + name, maxbits - mask); + } + if (mask < 3) + { + DBG1(DBG_CFG, "HA pool '%s' too small, skipped", name); + base->destroy(base); + continue; + } + + INIT(pool, + .name = strdup(name), + .base = base, + .size = (1 << mask), + ); + pool->mask = calloc(pool->size / 8, 1); + /* do not use first/last address of pool */ + pool->mask[0] |= 0x01; + pool->mask[pool->size / 8 - 1] |= 0x80; + + DBG1(DBG_CFG, "loaded HA pool '%s' %H/%d (%d addresses)", + pool->name, pool->base, maxbits - mask, pool->size - 2); + this->pools->insert_last(this->pools, pool); + } + enumerator->destroy(enumerator); +} + +/** + * See header + */ +ha_attribute_t *ha_attribute_create(ha_kernel_t *kernel, ha_segments_t *segments) +{ + private_ha_attribute_t *this; + + INIT(this, + .public = { + .provider = { + .acquire_address = _acquire_address, + .release_address = _release_address, + .create_attribute_enumerator = enumerator_create_empty, + }, + .reserve = _reserve, + .destroy = _destroy, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .pools = linked_list_create(), + .kernel = kernel, + .segments = segments, + ); + + load_pools(this); + + return &this->public; +} diff --git a/src/libcharon/plugins/ha/ha_attribute.h b/src/libcharon/plugins/ha/ha_attribute.h new file mode 100644 index 000000000..d1e4f5e89 --- /dev/null +++ b/src/libcharon/plugins/ha/ha_attribute.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup ha_attribute ha_attribute + * @{ @ingroup ha + */ + +#ifndef HA_ATTRIBUTE_H_ +#define HA_ATTRIBUTE_H_ + +#include "ha_kernel.h" +#include "ha_segments.h" + +#include <attributes/attribute_provider.h> + +typedef struct ha_attribute_t ha_attribute_t; + +/** + * A HA enabled in memory address pool attribute provider. + */ +struct ha_attribute_t { + + /** + * Implements attribute provider interface. + */ + attribute_provider_t provider; + + /** + * Reserve an address for a passive IKE_SA. + * + * @param name pool name to reserve address in + * @param address address to reserve + */ + void (*reserve)(ha_attribute_t *this, char *name, host_t *address); + + /** + * Destroy a ha_attribute_t. + */ + void (*destroy)(ha_attribute_t *this); +}; + +/** + * Create a ha_attribute instance. + */ +ha_attribute_t *ha_attribute_create(ha_kernel_t *kernel, ha_segments_t *segments); + +#endif /** HA_ATTRIBUTE_H_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c new file mode 100644 index 000000000..1ebc33ca4 --- /dev/null +++ b/src/libcharon/plugins/ha/ha_cache.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "ha_cache.h" + +#include <utils/hashtable.h> +#include <utils/linked_list.h> +#include <threading/mutex.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_ha_cache_t private_ha_cache_t; + +/** + * Private data of an ha_cache_t object. + */ +struct private_ha_cache_t { + + /** + * Public ha_cache_t interface. + */ + ha_cache_t public; + + /** + * Kernel helper functions + */ + ha_kernel_t *kernel; + + /** + * Socket to send sync messages over + */ + ha_socket_t *socket; + + /** + * Total number of segments + */ + u_int count; + + /** + * cached entries (ike_sa_t, entry_t) + */ + hashtable_t *cache; + + /** + * Mutex to lock cache + */ + mutex_t *mutex; +}; + +/** + * Hashtable hash function + */ +static u_int hash(void *key) +{ + return (uintptr_t)key; +} + +/** + * Hashtable equals function + */ +static bool equals(void *a, void *b) +{ + return a == b; +} + +/** + * Cache entry for an IKE_SA + */ +typedef struct { + /* segment this entry is associate to */ + u_int segment; + /* ADD message */ + ha_message_t *add; + /* list of updates UPDATE message */ + linked_list_t *updates; + /* last initiator mid */ + ha_message_t *midi; + /* last responder mid */ + ha_message_t *midr; +} entry_t; + +/** + * Create a entry with an add message + */ +static entry_t *entry_create(ha_message_t *add) +{ + entry_t *entry; + + INIT(entry, + .add = add, + .updates = linked_list_create(), + ); + return entry; +} + +/** + * clean up a entry + */ +static void entry_destroy(entry_t *entry) +{ + entry->updates->destroy_offset(entry->updates, + offsetof(ha_message_t, destroy)); + entry->add->destroy(entry->add); + DESTROY_IF(entry->midi); + DESTROY_IF(entry->midr); + free(entry); +} + +METHOD(ha_cache_t, cache, void, + private_ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message) +{ + entry_t *entry; + + this->mutex->lock(this->mutex); + switch (message->get_type(message)) + { + case HA_IKE_ADD: + entry = entry_create(message); + entry = this->cache->put(this->cache, ike_sa, entry); + if (entry) + { + entry_destroy(entry); + } + break; + case HA_IKE_UPDATE: + entry = this->cache->get(this->cache, ike_sa); + if (entry) + { + entry->segment = this->kernel->get_segment(this->kernel, + ike_sa->get_other_host(ike_sa)); + entry->updates->insert_last(entry->updates, message); + break; + } + message->destroy(message); + break; + case HA_IKE_MID_INITIATOR: + entry = this->cache->get(this->cache, ike_sa); + if (entry) + { + DESTROY_IF(entry->midi); + entry->midi = message; + break; + } + message->destroy(message); + break; + case HA_IKE_MID_RESPONDER: + entry = this->cache->get(this->cache, ike_sa); + if (entry) + { + DESTROY_IF(entry->midr); + entry->midr = message; + break; + } + message->destroy(message); + break; + case HA_IKE_DELETE: + entry = this->cache->remove(this->cache, ike_sa); + if (entry) + { + entry_destroy(entry); + } + message->destroy(message); + break; + default: + message->destroy(message); + break; + } + this->mutex->unlock(this->mutex); +} + +METHOD(ha_cache_t, delete_, void, + private_ha_cache_t *this, ike_sa_t *ike_sa) +{ + entry_t *entry; + + entry = this->cache->remove(this->cache, ike_sa); + if (entry) + { + entry_destroy(entry); + } +} + +/** + * Rekey all children of an IKE_SA + */ +static status_t rekey_children(ike_sa_t *ike_sa) +{ + iterator_t *iterator; + child_sa_t *child_sa; + status_t status = SUCCESS; + + iterator = ike_sa->create_child_sa_iterator(ike_sa); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + DBG1(DBG_CFG, "resyncing CHILD_SA"); + status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + if (status == DESTROY_ME) + { + break; + } + } + iterator->destroy(iterator); + return status; +} + +/** + * Trigger rekeying of CHILD_SA in segment + */ +static void rekey_segment(private_ha_cache_t *this, u_int segment) +{ + ike_sa_t *ike_sa; + enumerator_t *enumerator; + linked_list_t *list; + ike_sa_id_t *id; + + list = linked_list_create(); + + enumerator = charon->ike_sa_manager->create_enumerator( + charon->ike_sa_manager); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + this->kernel->get_segment(this->kernel, + ike_sa->get_other_host(ike_sa)) == segment) + { + id = ike_sa->get_id(ike_sa); + list->insert_last(list, id->clone(id)); + } + } + enumerator->destroy(enumerator); + + while (list->remove_last(list, (void**)&id) == SUCCESS) + { + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + if (ike_sa) + { + if (rekey_children(ike_sa) != DESTROY_ME) + { + charon->ike_sa_manager->checkin( + charon->ike_sa_manager, ike_sa); + } + else + { + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + } + id->destroy(id); + } + list->destroy(list); +} + +METHOD(ha_cache_t, resync, void, + private_ha_cache_t *this, u_int segment) +{ + enumerator_t *enumerator, *updates; + ike_sa_t *ike_sa; + entry_t *entry; + ha_message_t *message; + + DBG1(DBG_CFG, "resyncing HA segment %d", segment); + + this->mutex->lock(this->mutex); + enumerator = this->cache->create_enumerator(this->cache); + while (enumerator->enumerate(enumerator, &ike_sa, &entry)) + { + if (entry->segment == segment) + { + this->socket->push(this->socket, entry->add); + updates = entry->updates->create_enumerator(entry->updates); + while (updates->enumerate(updates, &message)) + { + this->socket->push(this->socket, message); + } + updates->destroy(updates); + if (entry->midi) + { + this->socket->push(this->socket, entry->midi); + } + if (entry->midr) + { + this->socket->push(this->socket, entry->midr); + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + rekey_segment(this, segment); +} + +/** + * Request a resync of all segments + */ +static job_requeue_t request_resync(private_ha_cache_t *this) +{ + ha_message_t *message; + int i; + + DBG1(DBG_CFG, "requesting HA resynchronization"); + + message = ha_message_create(HA_RESYNC); + for (i = 1; i <= this->count; i++) + { + message->add_attribute(message, HA_SEGMENT, i); + } + this->socket->push(this->socket, message); + message->destroy(message); + return JOB_REQUEUE_NONE; +} + +METHOD(ha_cache_t, destroy, void, + private_ha_cache_t *this) +{ + this->cache->destroy(this->cache); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket, + bool sync, u_int count) +{ + private_ha_cache_t *this; + + INIT(this, + .public = { + .cache = _cache, + .delete = _delete_, + .resync = _resync, + .destroy = _destroy, + }, + .count = count, + .kernel = kernel, + .socket = socket, + .cache = hashtable_create(hash, equals, 8), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + if (sync) + { + /* request a resync as soon as we are up */ + charon->scheduler->schedule_job(charon->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)request_resync, + this, NULL, NULL), 1); + } + return &this->public; +} diff --git a/src/libcharon/plugins/ha/ha_cache.h b/src/libcharon/plugins/ha/ha_cache.h new file mode 100644 index 000000000..39f1947a8 --- /dev/null +++ b/src/libcharon/plugins/ha/ha_cache.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup ha_cache ha_cache + * @{ @ingroup ha + */ + +#ifndef HA_CACHE_H_ +#define HA_CACHE_H_ + +typedef struct ha_cache_t ha_cache_t; + +#include "ha_message.h" +#include "ha_kernel.h" +#include "ha_socket.h" + +#include <utils/enumerator.h> + +#include <sa/ike_sa.h> + +/** + * HA message caching facility, allows reintegration of new nodes. + */ +struct ha_cache_t { + + /** + * Cache an IKE specific message. + * + * @param ike_sa associated IKE_SA + * @param message message to cache + */ + void (*cache)(ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message); + + /** + * Delete a cache entry for an IKE_SA. + * + * @param ike_sa cache entry to delete + */ + void (*delete)(ha_cache_t *this, ike_sa_t *ike_sa); + + /** + * Resync a segment to the node using the cached messages. + * + * @param segment segment to resync + */ + void (*resync)(ha_cache_t *this, u_int segment); + + /** + * Destroy a ha_cache_t. + */ + void (*destroy)(ha_cache_t *this); +}; + +/** + * Create a ha_cache instance. + * + * @param kernel kernel helper + * @param socket socket to send resync messages + * @param resync request a resync during startup? + * @param count total number of segments + */ +ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket, + bool resync, u_int count); + +#endif /** HA_CACHE_H_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index 2eb8e27f6..1a9425423 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -36,22 +36,30 @@ struct private_ha_child_t { * tunnel securing sync messages */ ha_tunnel_t *tunnel; + + /** + * Segment handling + */ + ha_segments_t *segments; + + /** + * Kernel helper + */ + ha_kernel_t *kernel; }; -/** - * Implementation of listener_t.child_keys - */ -static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa, - child_sa_t *child_sa, diffie_hellman_t *dh, - chunk_t nonce_i, chunk_t nonce_r) +METHOD(listener_t, child_keys, bool, + private_ha_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool initiator, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r) { ha_message_t *m; chunk_t secret; proposal_t *proposal; u_int16_t alg, len; - linked_list_t *list; + linked_list_t *local_ts, *remote_ts; enumerator_t *enumerator; traffic_selector_t *ts; + u_int seg_i, seg_o; if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ @@ -61,6 +69,7 @@ static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa, m = ha_message_create(HA_CHILD_ADD); m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_INITIATOR, (u_int8_t)initiator); m->add_attribute(m, HA_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE)); m->add_attribute(m, HA_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE)); m->add_attribute(m, HA_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE)); @@ -90,31 +99,40 @@ static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa, chunk_clear(&secret); } - list = child_sa->get_traffic_selectors(child_sa, TRUE); - enumerator = list->create_enumerator(list); + local_ts = child_sa->get_traffic_selectors(child_sa, TRUE); + enumerator = local_ts->create_enumerator(local_ts); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_LOCAL_TS, ts); } enumerator->destroy(enumerator); - list = child_sa->get_traffic_selectors(child_sa, FALSE); - enumerator = list->create_enumerator(list); + remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE); + enumerator = remote_ts->create_enumerator(remote_ts); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_REMOTE_TS, ts); } enumerator->destroy(enumerator); + seg_i = this->kernel->get_segment_spi(this->kernel, + ike_sa->get_my_host(ike_sa), child_sa->get_spi(child_sa, TRUE)); + seg_o = this->kernel->get_segment_spi(this->kernel, + ike_sa->get_other_host(ike_sa), child_sa->get_spi(child_sa, FALSE)); + DBG1(DBG_CFG, "handling HA CHILD_SA %s{%d} %#R=== %#R " + "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa), + child_sa->get_reqid(child_sa), local_ts, remote_ts, + seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", + seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); + this->socket->push(this->socket, m); + m->destroy(m); return TRUE; } -/** - * Implementation of listener_t.child_state_change - */ -static bool child_state_change(private_ha_child_t *this, ike_sa_t *ike_sa, - child_sa_t *child_sa, child_sa_state_t state) +METHOD(listener_t, child_state_change, bool, + private_ha_child_t *this, ike_sa_t *ike_sa, + child_sa_t *child_sa, child_sa_state_t state) { if (!ike_sa || ike_sa->get_state(ike_sa) == IKE_PASSIVE || @@ -138,14 +156,13 @@ static bool child_state_change(private_ha_child_t *this, ike_sa_t *ike_sa, m->add_attribute(m, HA_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE)); this->socket->push(this->socket, m); + m->destroy(m); } return TRUE; } -/** - * Implementation of ha_child_t.destroy. - */ -static void destroy(private_ha_child_t *this) +METHOD(ha_child_t, destroy, void, + private_ha_child_t *this) { free(this); } @@ -153,17 +170,24 @@ static void destroy(private_ha_child_t *this) /** * See header */ -ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel) +ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel, + ha_segments_t *segments, ha_kernel_t *kernel) { - private_ha_child_t *this = malloc_thing(private_ha_child_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.child_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys; - this->public.listener.child_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state))child_state_change; - this->public.destroy = (void(*)(ha_child_t*))destroy; - - this->socket = socket; - this->tunnel = tunnel; + private_ha_child_t *this; + + INIT(this, + .public = { + .listener = { + .child_keys = _child_keys, + .child_state_change = _child_state_change, + }, + .destroy = _destroy, + }, + .socket = socket, + .tunnel = tunnel, + .segments = segments, + .kernel = kernel, + ); return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_child.h b/src/libcharon/plugins/ha/ha_child.h index ea83495f7..56cd769ba 100644 --- a/src/libcharon/plugins/ha/ha_child.h +++ b/src/libcharon/plugins/ha/ha_child.h @@ -21,14 +21,15 @@ #ifndef HA_CHILD_H_ #define HA_CHILD_H_ +typedef struct ha_child_t ha_child_t; + #include "ha_socket.h" #include "ha_tunnel.h" #include "ha_segments.h" +#include "ha_kernel.h" #include <daemon.h> -typedef struct ha_child_t ha_child_t; - /** * Listener to synchronize CHILD_SAs. */ @@ -50,8 +51,11 @@ struct ha_child_t { * * @param socket socket to use for sending synchronization messages * @param tunnel tunnel securing sync messages, if any + * @param segments segment handling + * @param kernel kernel helper * @return CHILD listener */ -ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel); +ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel, + ha_segments_t *segments, ha_kernel_t *kernel); -#endif /* HA_CHILD_ @}*/ +#endif /** HA_CHILD_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c index 441d26d9e..e188a8484 100644 --- a/src/libcharon/plugins/ha/ha_ctl.c +++ b/src/libcharon/plugins/ha/ha_ctl.c @@ -45,6 +45,11 @@ struct private_ha_ctl_t { ha_segments_t *segments; /** + * Resynchronization message cache + */ + ha_cache_t *cache; + + /** * FIFO reader thread */ callback_job_t *job; @@ -84,7 +89,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this) this->segments->deactivate(this->segments, segment, TRUE); break; case '*': - this->segments->resync(this->segments, segment); + this->cache->resync(this->cache, segment); break; default: break; @@ -96,10 +101,8 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this) return JOB_REQUEUE_DIRECT; } -/** - * Implementation of ha_ctl_t.destroy. - */ -static void destroy(private_ha_ctl_t *this) +METHOD(ha_ctl_t, destroy, void, + private_ha_ctl_t *this) { this->job->cancel(this->job); free(this); @@ -108,11 +111,17 @@ static void destroy(private_ha_ctl_t *this) /** * See header */ -ha_ctl_t *ha_ctl_create(ha_segments_t *segments) +ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache) { - private_ha_ctl_t *this = malloc_thing(private_ha_ctl_t); + private_ha_ctl_t *this; - this->public.destroy = (void(*)(ha_ctl_t*))destroy; + INIT(this, + .public = { + .destroy = _destroy, + }, + .segments = segments, + .cache = cache, + ); if (access(HA_FIFO, R_OK|W_OK) != 0) { @@ -123,7 +132,6 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments) } } - this->segments = segments; this->job = callback_job_create((callback_job_cb_t)dispatch_fifo, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/libcharon/plugins/ha/ha_ctl.h b/src/libcharon/plugins/ha/ha_ctl.h index f33a809be..1e717832a 100644 --- a/src/libcharon/plugins/ha/ha_ctl.h +++ b/src/libcharon/plugins/ha/ha_ctl.h @@ -22,6 +22,7 @@ #define HA_CTL_H_ #include "ha_segments.h" +#include "ha_cache.h" typedef struct ha_ctl_t ha_ctl_t; @@ -40,8 +41,9 @@ struct ha_ctl_t { * Create a ha_ctl instance. * * @param segments segments to control + * @param cache message cache for resynchronization * @return HA control interface */ -ha_ctl_t *ha_ctl_create(ha_segments_t *segments); +ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache); -#endif /* HA_CTL_ @}*/ +#endif /** HA_CTL_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 7df2f1fa8..3bc426ea0 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -41,6 +41,21 @@ struct private_ha_dispatcher_t { ha_segments_t *segments; /** + * Cache for resync + */ + ha_cache_t *cache; + + /** + * Kernel helper + */ + ha_kernel_t *kernel; + + /** + * HA enabled pool + */ + ha_attribute_t *attr; + + /** * Dispatcher job */ callback_job_t *job; @@ -153,6 +168,8 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message old_sa = NULL; } ike_sa->set_state(ike_sa, IKE_CONNECTING); + this->cache->cache(this->cache, ike_sa, message); + message = NULL; charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } else @@ -167,6 +184,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message { charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa); } + DESTROY_IF(message); } /** @@ -201,6 +219,8 @@ static void process_ike_update(private_ha_dispatcher_t *this, enumerator_t *enumerator; ike_sa_t *ike_sa = NULL; peer_cfg_t *peer_cfg = NULL; + auth_cfg_t *auth; + bool received_vip = FALSE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -222,6 +242,11 @@ static void process_ike_update(private_ha_dispatcher_t *this, case HA_REMOTE_ID: ike_sa->set_other_id(ike_sa, value.id->clone(value.id)); break; + case HA_REMOTE_EAP_ID: + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_EAP_IDENTITY, value.id->clone(value.id)); + ike_sa->add_auth_cfg(ike_sa, FALSE, auth); + break; case HA_LOCAL_ADDR: ike_sa->set_my_host(ike_sa, value.host->clone(value.host)); break; @@ -233,6 +258,7 @@ static void process_ike_update(private_ha_dispatcher_t *this, break; case HA_REMOTE_VIP: ike_sa->set_virtual_ip(ike_sa, FALSE, value.host); + received_vip = TRUE; break; case HA_ADDITIONAL_ADDR: ike_sa->add_additional_address(ike_sa, @@ -265,12 +291,6 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN); set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); break; - case HA_INITIATE_MID: - ike_sa->set_message_id(ike_sa, TRUE, value.u32); - break; - case HA_RESPOND_MID: - ike_sa->set_message_id(ike_sa, FALSE, value.u32); - break; default: break; } @@ -282,10 +302,81 @@ static void process_ike_update(private_ha_dispatcher_t *this, if (ike_sa->get_state(ike_sa) == IKE_CONNECTING && ike_sa->get_peer_cfg(ike_sa)) { + DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]", + ike_sa->get_name(ike_sa), + ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa), + ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa)); ike_sa->set_state(ike_sa, IKE_PASSIVE); } + if (received_vip) + { + host_t *vip; + char *pool; + + peer_cfg = ike_sa->get_peer_cfg(ike_sa); + vip = ike_sa->get_virtual_ip(ike_sa, FALSE); + if (peer_cfg && vip) + { + pool = peer_cfg->get_pool(peer_cfg); + if (pool) + { + this->attr->reserve(this->attr, pool, vip); + } + } + } + this->cache->cache(this->cache, ike_sa, message); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } + else + { + DBG1(DBG_CFG, "passive HA IKE_SA to update not found"); + message->destroy(message); + } +} + +/** + * Process messages of type IKE_MID_INITIATOR/RESPONDER + */ +static void process_ike_mid(private_ha_dispatcher_t *this, + ha_message_t *message, bool initiator) +{ + ha_message_attribute_t attribute; + ha_message_value_t value; + enumerator_t *enumerator; + ike_sa_t *ike_sa = NULL; + u_int32_t mid = 0; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + switch (attribute) + { + case HA_IKE_ID: + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); + break; + case HA_MID: + mid = value.u32; + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (ike_sa) + { + if (mid) + { + ike_sa->set_message_id(ike_sa, initiator, mid); + } + this->cache->cache(this->cache, ike_sa, message); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + message->destroy(message); + } } /** @@ -297,7 +388,7 @@ static void process_ike_delete(private_ha_dispatcher_t *this, ha_message_attribute_t attribute; ha_message_value_t value; enumerator_t *enumerator; - ike_sa_t *ike_sa; + ike_sa_t *ike_sa = NULL; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -307,17 +398,22 @@ static void process_ike_delete(private_ha_dispatcher_t *this, case HA_IKE_ID: ike_sa = charon->ike_sa_manager->checkout( charon->ike_sa_manager, value.ike_sa_id); - if (ike_sa) - { - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, ike_sa); - } break; default: break; } } enumerator->destroy(enumerator); + if (ike_sa) + { + this->cache->cache(this->cache, ike_sa, message); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + } + else + { + message->destroy(message); + } } /** @@ -366,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_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; linked_list_t *local_ts, *remote_ts; @@ -381,11 +478,13 @@ static void process_child_add(private_ha_dispatcher_t *this, case HA_IKE_ID: ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, value.ike_sa_id); - initiator = value.ike_sa_id->is_initiator(value.ike_sa_id); break; case HA_CONFIG_NAME: config_name = value.str; break; + case HA_INITIATOR: + initiator = value.u8; + break; case HA_INBOUND_SPI: inbound_spi = value.u32; break; @@ -431,6 +530,7 @@ static void process_child_add(private_ha_dispatcher_t *this, if (!ike_sa) { DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found"); + message->destroy(message); return; } config = find_child_cfg(ike_sa, config_name); @@ -438,6 +538,7 @@ static void process_child_add(private_ha_dispatcher_t *this, { DBG1(DBG_CHD, "HA is missing nodes child configuration"); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + message->destroy(message); return; } @@ -524,15 +625,27 @@ static void process_child_add(private_ha_dispatcher_t *this, local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + message->destroy(message); return; } + seg_i = this->kernel->get_segment_spi(this->kernel, + ike_sa->get_my_host(ike_sa), inbound_spi); + seg_o = this->kernel->get_segment_spi(this->kernel, + ike_sa->get_other_host(ike_sa), outbound_spi); + + DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R=== %#R " + "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa), + child_sa->get_reqid(child_sa), local_ts, remote_ts, + seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", + seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); child_sa->add_policies(child_sa, local_ts, remote_ts); local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy)); remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy)); child_sa->set_state(child_sa, CHILD_INSTALLED); ike_sa->add_child_sa(ike_sa, child_sa); + message->destroy(message); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } @@ -546,6 +659,8 @@ static void process_child_delete(private_ha_dispatcher_t *this, ha_message_value_t value; enumerator_t *enumerator; ike_sa_t *ike_sa = NULL; + child_sa_t *child_sa; + u_int32_t spi = 0; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -557,20 +672,24 @@ static void process_child_delete(private_ha_dispatcher_t *this, value.ike_sa_id); break; case HA_INBOUND_SPI: - if (ike_sa) - { - ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, value.u32); - } + spi = value.u32; break; default: break; } } + enumerator->destroy(enumerator); + if (ike_sa) { + child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE); + if (child_sa) + { + ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi); + } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } - enumerator->destroy(enumerator); + message->destroy(message); } /** @@ -605,6 +724,7 @@ static void process_segment(private_ha_dispatcher_t *this, } } enumerator->destroy(enumerator); + message->destroy(message); } /** @@ -633,6 +753,7 @@ static void process_status(private_ha_dispatcher_t *this, enumerator->destroy(enumerator); this->segments->handle_status(this->segments, mask); + message->destroy(message); } /** @@ -651,13 +772,14 @@ static void process_resync(private_ha_dispatcher_t *this, switch (attribute) { case HA_SEGMENT: - this->segments->resync(this->segments, value.u16); + this->cache->resync(this->cache, value.u16); break; default: break; } } enumerator->destroy(enumerator); + message->destroy(message); } /** @@ -666,9 +788,16 @@ static void process_resync(private_ha_dispatcher_t *this, static job_requeue_t dispatch(private_ha_dispatcher_t *this) { ha_message_t *message; + ha_message_type_t type; message = this->socket->pull(this->socket); - switch (message->get_type(message)) + type = message->get_type(message); + if (type != HA_STATUS) + { + DBG2(DBG_CFG, "received HA %N message", ha_message_type_names, + message->get_type(message)); + } + switch (type) { case HA_IKE_ADD: process_ike_add(this, message); @@ -676,6 +805,12 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this) case HA_IKE_UPDATE: process_ike_update(this, message); break; + case HA_IKE_MID_INITIATOR: + process_ike_mid(this, message, TRUE); + break; + case HA_IKE_MID_RESPONDER: + process_ike_mid(this, message, FALSE); + break; case HA_IKE_DELETE: process_ike_delete(this, message); break; @@ -698,19 +833,15 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this) process_resync(this, message); break; default: - DBG1(DBG_CFG, "received unknown HA message type %d", - message->get_type(message)); + DBG1(DBG_CFG, "received unknown HA message type %d", type); + message->destroy(message); break; } - message->destroy(message); - return JOB_REQUEUE_DIRECT; } -/** - * Implementation of ha_dispatcher_t.destroy. - */ -static void destroy(private_ha_dispatcher_t *this) +METHOD(ha_dispatcher_t, destroy, void, + private_ha_dispatcher_t *this) { this->job->cancel(this->job); free(this); @@ -720,14 +851,22 @@ static void destroy(private_ha_dispatcher_t *this) * See header */ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, - ha_segments_t *segments) + ha_segments_t *segments, ha_cache_t *cache, + ha_kernel_t *kernel, ha_attribute_t *attr) { - private_ha_dispatcher_t *this = malloc_thing(private_ha_dispatcher_t); - - this->public.destroy = (void(*)(ha_dispatcher_t*))destroy; - - this->socket = socket; - this->segments = segments; + private_ha_dispatcher_t *this; + + + INIT(this, + .public = { + .destroy = _destroy, + }, + .socket = socket, + .segments = segments, + .cache = cache, + .kernel = kernel, + .attr = attr, + ); this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.h b/src/libcharon/plugins/ha/ha_dispatcher.h index d2baace3f..105a40473 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.h +++ b/src/libcharon/plugins/ha/ha_dispatcher.h @@ -23,6 +23,9 @@ #include "ha_socket.h" #include "ha_segments.h" +#include "ha_cache.h" +#include "ha_kernel.h" +#include "ha_attribute.h" typedef struct ha_dispatcher_t ha_dispatcher_t; @@ -42,9 +45,13 @@ struct ha_dispatcher_t { * * @param socket socket to pull messages from * @param segments segments to control based on received messages + * @param cache message cache to use for resynchronization + * @param kernel kernel helper + * @param attr HA enabled pool * @return dispatcher object */ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket, - ha_segments_t *segments); + ha_segments_t *segments, ha_cache_t *cache, + ha_kernel_t *kernel, ha_attribute_t *attr); -#endif /* HA_DISPATCHER_ @}*/ +#endif /** HA_DISPATCHER_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index 1f025d0e5..1efba4e8f 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -36,6 +36,11 @@ struct private_ha_ike_t { * tunnel securing sync messages */ ha_tunnel_t *tunnel; + + /** + * message cache + */ + ha_cache_t *cache; }; /** @@ -62,12 +67,9 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext) return 0; } -/** - * Implementation of listener_t.ike_keys - */ -static bool ike_keys(private_ha_ike_t *this, ike_sa_t *ike_sa, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, - ike_sa_t *rekey) +METHOD(listener_t, ike_keys, bool, + private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey) { ha_message_t *m; chunk_t secret; @@ -120,14 +122,13 @@ static bool ike_keys(private_ha_ike_t *this, ike_sa_t *ike_sa, chunk_clear(&secret); this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); return TRUE; } -/** - * Implementation of listener_t.ike_updown - */ -static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up) +METHOD(listener_t, ike_updown, bool, + private_ha_ike_t *this, ike_sa_t *ike_sa, bool up) { ha_message_t *m; @@ -147,6 +148,7 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up) u_int32_t extension, condition; host_t *addr; ike_sa_id_t *id; + identification_t *eap_id; peer_cfg = ike_sa->get_peer_cfg(ike_sa); @@ -168,6 +170,11 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up) m->add_attribute(m, HA_IKE_ID, id); m->add_attribute(m, HA_LOCAL_ID, ike_sa->get_my_id(ike_sa)); m->add_attribute(m, HA_REMOTE_ID, ike_sa->get_other_id(ike_sa)); + eap_id = ike_sa->get_other_eap_id(ike_sa); + if (!eap_id->equals(eap_id, ike_sa->get_other_id(ike_sa))) + { + m->add_attribute(m, HA_REMOTE_EAP_ID, eap_id); + } m->add_attribute(m, HA_LOCAL_ADDR, ike_sa->get_my_host(ike_sa)); m->add_attribute(m, HA_REMOTE_ADDR, ike_sa->get_other_host(ike_sa)); m->add_attribute(m, HA_CONDITIONS, condition); @@ -186,24 +193,31 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up) m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); } this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); return TRUE; } -/** - * Implementation of listener_t.ike_rekey - */ -static bool ike_rekey(private_ha_ike_t *this, ike_sa_t *old, ike_sa_t *new) +METHOD(listener_t, ike_rekey, bool, + private_ha_ike_t *this, ike_sa_t *old, ike_sa_t *new) { ike_updown(this, old, FALSE); ike_updown(this, new, TRUE); return TRUE; } -/** - * Implementation of listener_t.message - */ -static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa, - message_t *message, bool incoming) +METHOD(listener_t, ike_state_change, bool, + private_ha_ike_t *this, ike_sa_t *ike_sa, ike_sa_state_t new) +{ + /* delete any remaining cache entry if IKE_SA gets destroyed */ + if (new == IKE_DESTROYING) + { + this->cache->delete(this->cache, ike_sa); + } + return TRUE; +} + +METHOD(listener_t, message_hook, bool, + private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming) { if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ @@ -214,20 +228,19 @@ static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa, message->get_request(message)) { /* we sync on requests, but skip it on IKE_SA_INIT */ ha_message_t *m; - u_int32_t mid; - m = ha_message_create(HA_IKE_UPDATE); - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - mid = message->get_message_id(message) + 1; if (incoming) { - m->add_attribute(m, HA_RESPOND_MID, mid); + m = ha_message_create(HA_IKE_MID_RESPONDER); } else { - m->add_attribute(m, HA_INITIATE_MID, mid); + m = ha_message_create(HA_IKE_MID_INITIATOR); } + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_MID, message->get_message_id(message) + 1); this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); } if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && message->get_exchange_type(message) == IKE_AUTH && @@ -245,15 +258,14 @@ static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa, m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); m->add_attribute(m, HA_REMOTE_VIP, vip); this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); } } return TRUE; } -/** - * Implementation of ha_ike_t.destroy. - */ -static void destroy(private_ha_ike_t *this) +METHOD(ha_ike_t, destroy, void, + private_ha_ike_t *this) { free(this); } @@ -261,19 +273,26 @@ static void destroy(private_ha_ike_t *this) /** * See header */ -ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel) +ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel, + ha_cache_t *cache) { - private_ha_ike_t *this = malloc_thing(private_ha_ike_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys; - this->public.listener.ike_updown = (bool(*)(listener_t*,ike_sa_t *ike_sa, bool up))ike_updown; - this->public.listener.ike_rekey = (bool(*)(listener_t*,ike_sa_t *old, ike_sa_t *new))ike_rekey; - this->public.listener.message = (bool(*)(listener_t*, ike_sa_t *, message_t *,bool))message_hook; - this->public.destroy = (void(*)(ha_ike_t*))destroy; - - this->socket = socket; - this->tunnel = tunnel; + private_ha_ike_t *this; + + INIT(this, + .public = { + .listener = { + .ike_keys = _ike_keys, + .ike_updown = _ike_updown, + .ike_rekey = _ike_rekey, + .ike_state_change = _ike_state_change, + .message = _message_hook, + }, + .destroy = _destroy, + }, + .socket = socket, + .tunnel = tunnel, + .cache = cache, + ); return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_ike.h b/src/libcharon/plugins/ha/ha_ike.h index 9de210e67..b22cd6250 100644 --- a/src/libcharon/plugins/ha/ha_ike.h +++ b/src/libcharon/plugins/ha/ha_ike.h @@ -21,14 +21,15 @@ #ifndef HA_IKE_H_ #define HA_IKE_H_ +typedef struct ha_ike_t ha_ike_t; + #include "ha_socket.h" #include "ha_tunnel.h" #include "ha_segments.h" +#include "ha_cache.h" #include <daemon.h> -typedef struct ha_ike_t ha_ike_t; - /** * Listener to synchronize IKE_SAs. */ @@ -50,8 +51,10 @@ struct ha_ike_t { * * @param socket socket to use for sending synchronization messages * @param tunnel tunnel securing sync messages, if any + * @param cache message cache * @return IKE listener */ -ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel); +ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel, + ha_cache_t *cache); -#endif /* HA_IKE_ @}*/ +#endif /** HA_IKE_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c index 0ad9c22c3..10a63453a 100644 --- a/src/libcharon/plugins/ha/ha_kernel.c +++ b/src/libcharon/plugins/ha/ha_kernel.c @@ -52,24 +52,57 @@ struct private_ha_kernel_t { }; /** - * Implementation of ha_kernel_t.in_segment + * Segmentate a calculated hash */ -static bool in_segment(private_ha_kernel_t *this, host_t *host, u_int segment) +static u_int hash2segment(private_ha_kernel_t *this, u_int64_t hash) +{ + return ((hash * this->count) >> 32) + 1; +} + +/** + * Get a host as an integer for hashing + */ +static u_int32_t host2int(host_t *host) { if (host->get_family(host) == AF_INET) { - unsigned long hash; - u_int32_t addr; + return *(u_int32_t*)host->get_address(host).ptr; + } + return 0; +} - addr = *(u_int32_t*)host->get_address(host).ptr; - hash = jhash_1word(ntohl(addr), this->initval); +METHOD(ha_kernel_t, get_segment, u_int, + private_ha_kernel_t *this, host_t *host) +{ + unsigned long hash; + u_int32_t addr; - if ((((u_int64_t)hash * this->count) >> 32) + 1 == segment) - { - return TRUE; - } - } - return FALSE; + addr = host2int(host); + hash = jhash_1word(ntohl(addr), this->initval); + + return hash2segment(this, hash); +} + +METHOD(ha_kernel_t, get_segment_spi, u_int, + private_ha_kernel_t *this, host_t *host, u_int32_t spi) +{ + unsigned long hash; + u_int32_t addr; + + addr = host2int(host); + hash = jhash_2words(ntohl(addr), ntohl(spi), this->initval); + + return hash2segment(this, hash); +} + +METHOD(ha_kernel_t, get_segment_int, u_int, + private_ha_kernel_t *this, int n) +{ + unsigned long hash; + + hash = jhash_1word(ntohl(n), this->initval); + + return hash2segment(this, hash); } /** @@ -142,10 +175,8 @@ static segment_mask_t get_active(private_ha_kernel_t *this, char *file) return mask; } -/** - * Implementation of ha_kernel_t.activate - */ -static void activate(private_ha_kernel_t *this, u_int segment) +METHOD(ha_kernel_t, activate, void, + private_ha_kernel_t *this, u_int segment) { enumerator_t *enumerator; char *file; @@ -158,10 +189,8 @@ static void activate(private_ha_kernel_t *this, u_int segment) enumerator->destroy(enumerator); } -/** - * Implementation of ha_kernel_t.deactivate - */ -static void deactivate(private_ha_kernel_t *this, u_int segment) +METHOD(ha_kernel_t, deactivate, void, + private_ha_kernel_t *this, u_int segment) { enumerator_t *enumerator; char *file; @@ -199,10 +228,8 @@ static void disable_all(private_ha_kernel_t *this) enumerator->destroy(enumerator); } -/** - * Implementation of ha_kernel_t.destroy. - */ -static void destroy(private_ha_kernel_t *this) +METHOD(ha_kernel_t, destroy, void, + private_ha_kernel_t *this) { free(this); } @@ -212,15 +239,20 @@ static void destroy(private_ha_kernel_t *this) */ ha_kernel_t *ha_kernel_create(u_int count) { - private_ha_kernel_t *this = malloc_thing(private_ha_kernel_t); - - this->public.in_segment = (bool(*)(ha_kernel_t*, host_t *host, u_int segment))in_segment; - this->public.activate = (void(*)(ha_kernel_t*, u_int segment))activate; - this->public.deactivate = (void(*)(ha_kernel_t*, u_int segment))deactivate; - this->public.destroy = (void(*)(ha_kernel_t*))destroy; + private_ha_kernel_t *this; - this->initval = 0; - this->count = count; + INIT(this, + .public = { + .get_segment = _get_segment, + .get_segment_spi = _get_segment_spi, + .get_segment_int = _get_segment_int, + .activate = _activate, + .deactivate = _deactivate, + .destroy = _destroy, + }, + .initval = 0, + .count = count, + ); disable_all(this); diff --git a/src/libcharon/plugins/ha/ha_kernel.h b/src/libcharon/plugins/ha/ha_kernel.h index b37cc7667..7b56f1e3a 100644 --- a/src/libcharon/plugins/ha/ha_kernel.h +++ b/src/libcharon/plugins/ha/ha_kernel.h @@ -31,13 +31,28 @@ typedef struct ha_kernel_t ha_kernel_t; struct ha_kernel_t { /** - * Check if a host is in a segment. + * Get the segment a host is in. * - * @param host host to check - * @param segment segment - * @return TRUE if host belongs to segment + * @param host host to get segment for + * @return segment number */ - bool (*in_segment)(ha_kernel_t *this, host_t *host, u_int segment); + u_int (*get_segment)(ha_kernel_t *this, host_t *host); + + /** + * Get the segment a host/SPI is in, as used for CHILD_SA segmentation. + * + * @param host host to get segment for + * @param spi SPI to include in hash + * @return segment number + */ + u_int (*get_segment_spi)(ha_kernel_t *this, host_t *host, u_int32_t spi); + + /** + * Get the segment an arbitrary integer is in. + * + * @param n integer to segmentate + */ + u_int (*get_segment_int)(ha_kernel_t *this, int n); /** * Activate a segment at kernel level for all cluster addresses. @@ -63,8 +78,7 @@ struct ha_kernel_t { * Create a ha_kernel instance. * * @param count total number of segments to use - * @param active bitmask of initially active segments */ ha_kernel_t *ha_kernel_create(u_int count); -#endif /* HA_KERNEL_ @}*/ +#endif /** HA_KERNEL_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index 54b10f05d..7ce9cbe09 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -46,6 +46,20 @@ struct private_ha_message_t { chunk_t buf; }; +ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC, + "IKE_ADD", + "IKE_UPDATE", + "IKE_MID_INITIATOR", + "IKE_MID_RESPONDER", + "IKE_DELETE", + "CHILD_ADD", + "CHILD_DELETE", + "SEGMENT_DROP", + "SEGMENT_TAKE", + "STATUS", + "RESYNC", +); + typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t; /** @@ -93,10 +107,8 @@ struct ts_encoding_t { char encoding[]; } __attribute__((packed)); -/** - * Implementation of ha_message_t.get_type - */ -static ha_message_type_t get_type(private_ha_message_t *this) +METHOD(ha_message_t, get_type, ha_message_type_t, + private_ha_message_t *this) { return this->buf.ptr[1]; } @@ -119,11 +131,8 @@ static void check_buf(private_ha_message_t *this, size_t len) } } -/** - * Implementation of ha_message_t.add_attribute - */ -static void add_attribute(private_ha_message_t *this, - ha_message_attribute_t attribute, ...) +METHOD(ha_message_t, add_attribute, void, + private_ha_message_t *this, ha_message_attribute_t attribute, ...) { size_t len; va_list args; @@ -154,6 +163,7 @@ static void add_attribute(private_ha_message_t *this, /* identification_t* */ case HA_LOCAL_ID: case HA_REMOTE_ID: + case HA_REMOTE_EAP_ID: { identification_encoding_t *enc; identification_t *id; @@ -203,6 +213,7 @@ static void add_attribute(private_ha_message_t *this, break; } /* u_int8_t */ + case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: { @@ -237,8 +248,7 @@ static void add_attribute(private_ha_message_t *this, case HA_EXTENSIONS: case HA_INBOUND_SPI: case HA_OUTBOUND_SPI: - case HA_INITIATE_MID: - case HA_RESPOND_MID: + case HA_MID: { u_int32_t val; @@ -310,12 +320,9 @@ typedef struct { void *cleanup_data; } attribute_enumerator_t; -/** - * Implementation of create_attribute_enumerator().enumerate - */ -static bool attribute_enumerate(attribute_enumerator_t *this, - ha_message_attribute_t *attr_out, - ha_message_value_t *value) +METHOD(enumerator_t, attribute_enumerate, bool, + attribute_enumerator_t *this, ha_message_attribute_t *attr_out, + ha_message_value_t *value) { ha_message_attribute_t attr; @@ -354,6 +361,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this, /* identification_t* */ case HA_LOCAL_ID: case HA_REMOTE_ID: + case HA_REMOTE_EAP_ID: { identification_encoding_t *enc; @@ -417,6 +425,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this, return TRUE; } /* u_int8_t */ + case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: { @@ -453,8 +462,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this, case HA_EXTENSIONS: case HA_INBOUND_SPI: case HA_OUTBOUND_SPI: - case HA_INITIATE_MID: - case HA_RESPOND_MID: + case HA_MID: { if (this->buf.len < sizeof(u_int32_t)) { @@ -559,10 +567,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this, } } -/** - * Implementation of create_attribute_enumerator().destroy - */ -static void enum_destroy(attribute_enumerator_t *this) +METHOD(enumerator_t, enum_destroy, void, + attribute_enumerator_t *this) { if (this->cleanup) { @@ -571,35 +577,30 @@ static void enum_destroy(attribute_enumerator_t *this) free(this); } -/** - * Implementation of ha_message_t.create_attribute_enumerator - */ -static enumerator_t* create_attribute_enumerator(private_ha_message_t *this) +METHOD(ha_message_t, create_attribute_enumerator, enumerator_t*, + private_ha_message_t *this) { - attribute_enumerator_t *e = malloc_thing(attribute_enumerator_t); - - e->public.enumerate = (void*)attribute_enumerate; - e->public.destroy = (void*)enum_destroy; + attribute_enumerator_t *e; - e->buf = chunk_skip(this->buf, 2); - e->cleanup = NULL; - e->cleanup_data = NULL; + INIT(e, + .public = { + .enumerate = (void*)_attribute_enumerate, + .destroy = _enum_destroy, + }, + .buf = chunk_skip(this->buf, 2), + ); return &e->public; } -/** - * Implementation of ha_message_t.get_encoding - */ -static chunk_t get_encoding(private_ha_message_t *this) +METHOD(ha_message_t, get_encoding, chunk_t, + private_ha_message_t *this) { return this->buf; } -/** - * Implementation of ha_message_t.destroy. - */ -static void destroy(private_ha_message_t *this) +METHOD(ha_message_t, destroy, void, + private_ha_message_t *this) { free(this->buf.ptr); free(this); @@ -608,14 +609,17 @@ static void destroy(private_ha_message_t *this) static private_ha_message_t *ha_message_create_generic() { - private_ha_message_t *this = malloc_thing(private_ha_message_t); - - this->public.get_type = (ha_message_type_t(*)(ha_message_t*))get_type; - this->public.add_attribute = (void(*)(ha_message_t*, ha_message_attribute_t attribute, ...))add_attribute; - this->public.create_attribute_enumerator = (enumerator_t*(*)(ha_message_t*))create_attribute_enumerator; - this->public.get_encoding = (chunk_t(*)(ha_message_t*))get_encoding; - this->public.destroy = (void(*)(ha_message_t*))destroy; + private_ha_message_t *this; + INIT(this, + .public = { + .get_type = _get_type, + .add_attribute = _add_attribute, + .create_attribute_enumerator = _create_attribute_enumerator, + .get_encoding = _get_encoding, + .destroy = _destroy, + }, + ); return this; } diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index b2bc23724..50e11830f 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -30,7 +30,7 @@ /** * Protocol version of this implementation */ -#define HA_MESSAGE_VERSION 1 +#define HA_MESSAGE_VERSION 2 typedef struct ha_message_t ha_message_t; typedef enum ha_message_type_t ha_message_type_t; @@ -43,8 +43,12 @@ typedef union ha_message_value_t ha_message_value_t; enum ha_message_type_t { /** add a completely new IKE_SA */ HA_IKE_ADD = 1, - /** update an existing IKE_SA (message IDs, address update, ...) */ + /** update an existing IKE_SA (identities, address update, ...) */ HA_IKE_UPDATE, + /** update initiator message id */ + HA_IKE_MID_INITIATOR, + /** update responder message id */ + HA_IKE_MID_RESPONDER, /** delete an existing IKE_SA */ HA_IKE_DELETE, /** add a new CHILD_SA */ @@ -62,6 +66,11 @@ enum ha_message_type_t { }; /** + * Enum names for message types + */ +extern enum_name_t *ha_message_type_names; + +/** * Type of attributes contained in a message */ enum ha_message_attribute_t { @@ -73,6 +82,8 @@ enum ha_message_attribute_t { HA_LOCAL_ID, /** identification_t*, remote identity */ HA_REMOTE_ID, + /** identification_t*, remote EAP identity */ + HA_REMOTE_EAP_ID, /** host_t*, local address */ HA_LOCAL_ADDR, /** host_t*, remote address */ @@ -89,6 +100,8 @@ enum ha_message_attribute_t { HA_REMOTE_VIP, /** host_t*, additional MOBIKE peer address */ HA_ADDITIONAL_ADDR, + /** u_int8_t, initiator of an exchange, TRUE for local */ + HA_INITIATOR, /** chunk_t, initiators nonce */ HA_NONCE_I, /** chunk_t, responders nonce */ @@ -123,10 +136,8 @@ enum ha_message_attribute_t { HA_LOCAL_TS, /** traffic_selector_t*, remote traffic selector */ HA_REMOTE_TS, - /** u_int32_t, initiating message ID */ - HA_INITIATE_MID, - /** u_int32_t, responding message ID */ - HA_RESPOND_MID, + /** u_int32_t, message ID */ + HA_MID, /** u_int16_t, HA segment */ HA_SEGMENT, }; @@ -190,7 +201,6 @@ struct ha_message_t { /** * Create a new ha_message instance, ready for adding attributes * - * @param version protocol version to create a message from * @param type type of the message */ ha_message_t *ha_message_create(ha_message_type_t type); @@ -202,4 +212,4 @@ ha_message_t *ha_message_create(ha_message_type_t type); */ ha_message_t *ha_message_parse(chunk_t data); -#endif /* HA_MESSAGE_ @}*/ +#endif /** HA_MESSAGE_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index ea255c8ab..e722b4f3a 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -21,8 +21,11 @@ #include "ha_dispatcher.h" #include "ha_segments.h" #include "ha_ctl.h" +#include "ha_cache.h" +#include "ha_attribute.h" #include <daemon.h> +#include <hydra.h> #include <config/child_cfg.h> typedef struct private_ha_plugin_t private_ha_plugin_t; @@ -76,20 +79,31 @@ struct private_ha_plugin_t { * Segment control interface via FIFO */ ha_ctl_t *ctl; + + /** + * Message cache for resynchronization + */ + ha_cache_t *cache; + + /** + * Attribute provider + */ + ha_attribute_t *attr; }; -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_ha_plugin_t *this) +METHOD(plugin_t, destroy, void, + private_ha_plugin_t *this) { DESTROY_IF(this->ctl); + hydra->attributes->remove_provider(hydra->attributes, &this->attr->provider); charon->bus->remove_listener(charon->bus, &this->segments->listener); charon->bus->remove_listener(charon->bus, &this->ike->listener); charon->bus->remove_listener(charon->bus, &this->child->listener); this->ike->destroy(this->ike); this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); + this->attr->destroy(this->attr); + this->cache->destroy(this->cache); this->segments->destroy(this->segments); this->kernel->destroy(this->kernel); this->socket->destroy(this->socket); @@ -127,11 +141,9 @@ plugin_t *ha_plugin_create() return NULL; } - this = malloc_thing(private_ha_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - this->tunnel = NULL; - this->ctl = NULL; + INIT(this, + .public.plugin.destroy = _destroy, + ); if (secret) { @@ -146,17 +158,22 @@ plugin_t *ha_plugin_create() } this->kernel = ha_kernel_create(count); this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel, - count, strcmp(local, remote) > 0, monitor, resync); + count, strcmp(local, remote) > 0, monitor); + this->cache = ha_cache_create(this->kernel, this->socket, resync, count); if (fifo) { - this->ctl = ha_ctl_create(this->segments); + this->ctl = ha_ctl_create(this->segments, this->cache); } - this->dispatcher = ha_dispatcher_create(this->socket, this->segments); - this->ike = ha_ike_create(this->socket, this->tunnel); - this->child = ha_child_create(this->socket, this->tunnel); + this->attr = ha_attribute_create(this->kernel, this->segments); + this->dispatcher = ha_dispatcher_create(this->socket, this->segments, + this->cache, this->kernel, this->attr); + this->ike = ha_ike_create(this->socket, this->tunnel, this->cache); + this->child = ha_child_create(this->socket, this->tunnel, this->segments, + this->kernel); charon->bus->add_listener(charon->bus, &this->segments->listener); charon->bus->add_listener(charon->bus, &this->ike->listener); charon->bus->add_listener(charon->bus, &this->child->listener); + hydra->attributes->add_provider(hydra->attributes, &this->attr->provider); return &this->public.plugin; } diff --git a/src/libcharon/plugins/ha/ha_plugin.h b/src/libcharon/plugins/ha/ha_plugin.h index 1ae2fe6dd..d4d746f91 100644 --- a/src/libcharon/plugins/ha/ha_plugin.h +++ b/src/libcharon/plugins/ha/ha_plugin.h @@ -44,4 +44,4 @@ struct ha_plugin_t { plugin_t plugin; }; -#endif /* HA_PLUGIN_H_ @}*/ +#endif /** HA_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c index 2199671fc..be2d7e428 100644 --- a/src/libcharon/plugins/ha/ha_segments.c +++ b/src/libcharon/plugins/ha/ha_segments.c @@ -22,8 +22,8 @@ #include <utils/linked_list.h> #include <processing/jobs/callback_job.h> -#define HEARTBEAT_DELAY 1000 -#define HEARTBEAT_TIMEOUT 2100 +#define DEFAULT_HEARTBEAT_DELAY 1000 +#define DEFAULT_HEARTBEAT_TIMEOUT 2100 typedef struct private_ha_segments_t private_ha_segments_t; @@ -81,6 +81,16 @@ struct private_ha_segments_t { * Node number */ u_int node; + + /** + * Interval we send hearbeats + */ + int heartbeat_delay; + + /** + * Timeout for heartbeats received from other node + */ + int heartbeat_timeout; }; /** @@ -168,8 +178,8 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, { continue; } - if (this->kernel->in_segment(this->kernel, - ike_sa->get_other_host(ike_sa), segment)) + if (this->kernel->get_segment(this->kernel, + ike_sa->get_other_host(ike_sa)) == segment) { ike_sa->set_state(ike_sa, new); } @@ -183,6 +193,7 @@ static void enable_disable(private_ha_segments_t *this, u_int segment, message = ha_message_create(type); message->add_attribute(message, HA_SEGMENT, segment); this->socket->push(this->socket, message); + message->destroy(message); } } @@ -209,135 +220,37 @@ static void enable_disable_all(private_ha_segments_t *this, u_int segment, this->mutex->unlock(this->mutex); } -/** - * Implementation of ha_segments_t.activate - */ -static void activate(private_ha_segments_t *this, u_int segment, bool notify) +METHOD(ha_segments_t, activate, void, + private_ha_segments_t *this, u_int segment, bool notify) { enable_disable_all(this, segment, TRUE, notify); } -/** - * Implementation of ha_segments_t.deactivate - */ -static void deactivate(private_ha_segments_t *this, u_int segment, bool notify) +METHOD(ha_segments_t, deactivate, void, + private_ha_segments_t *this, u_int segment, bool notify) { enable_disable_all(this, segment, FALSE, notify); } -/** - * Rekey all children of an IKE_SA - */ -static status_t rekey_children(ike_sa_t *ike_sa) +METHOD(listener_t, alert_hook, bool, + private_ha_segments_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args) { - iterator_t *iterator; - child_sa_t *child_sa; - status_t status = SUCCESS; - - iterator = ike_sa->create_child_sa_iterator(ike_sa); - while (iterator->iterate(iterator, (void**)&child_sa)) - { - DBG1(DBG_CFG, "resyncing CHILD_SA"); - status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); - if (status == DESTROY_ME) - { - break; - } - } - iterator->destroy(iterator); - return status; -} - -/** - * Implementation of ha_segments_t.resync - */ -static void resync(private_ha_segments_t *this, u_int segment) -{ - ike_sa_t *ike_sa; - enumerator_t *enumerator; - linked_list_t *list; - ike_sa_id_t *id; - - list = linked_list_create(); - this->mutex->lock(this->mutex); - - if (segment > 0 && segment <= this->count) + if (alert == ALERT_SHUTDOWN_SIGNAL) { - DBG1(DBG_CFG, "resyncing HA segment %d", segment); - - /* we do the actual rekeying in a seperate loop to avoid rekeying - * an SA twice. */ - enumerator = charon->ike_sa_manager->create_enumerator( - charon->ike_sa_manager); - while (enumerator->enumerate(enumerator, &ike_sa)) + if (this->job) { - if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && - this->kernel->in_segment(this->kernel, - ike_sa->get_other_host(ike_sa), segment)) - { - id = ike_sa->get_id(ike_sa); - list->insert_last(list, id->clone(id)); - } + DBG1(DBG_CFG, "HA heartbeat active, dropping all segments"); + deactivate(this, 0, TRUE); } - enumerator->destroy(enumerator); - } - this->mutex->unlock(this->mutex); - - while (list->remove_last(list, (void**)&id) == SUCCESS) - { - ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); - id->destroy(id); - if (ike_sa) + else { - DBG1(DBG_CFG, "resyncing IKE_SA"); - if (ike_sa->rekey(ike_sa) != DESTROY_ME) - { - if (rekey_children(ike_sa) != DESTROY_ME) - { - charon->ike_sa_manager->checkin( - charon->ike_sa_manager, ike_sa); - continue; - } - } - charon->ike_sa_manager->checkin_and_destroy( - charon->ike_sa_manager, ike_sa); + DBG1(DBG_CFG, "no HA heartbeat active, closing IKE_SAs"); } } - list->destroy(list); -} - -/** - * Implementation of listener_t.alert - */ -static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa, - alert_t alert, va_list args) -{ - if (alert == ALERT_SHUTDOWN_SIGNAL) - { - deactivate(this, 0, TRUE); - } return TRUE; } /** - * Request a resync of all segments - */ -static job_requeue_t request_resync(private_ha_segments_t *this) -{ - ha_message_t *message; - int i; - - message = ha_message_create(HA_RESYNC); - for (i = 1; i <= this->count; i++) - { - message->add_attribute(message, HA_SEGMENT, i); - } - this->socket->push(this->socket, message); - return JOB_REQUEUE_NONE; -} - -/** * Monitor heartbeat activity of remote node */ static job_requeue_t watchdog(private_ha_segments_t *this) @@ -349,7 +262,7 @@ static job_requeue_t watchdog(private_ha_segments_t *this) pthread_cleanup_push((void*)this->mutex->unlock, this->mutex); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); timeout = this->condvar->timed_wait(this->condvar, this->mutex, - HEARTBEAT_TIMEOUT); + this->heartbeat_timeout); pthread_setcancelstate(oldstate, NULL); pthread_cleanup_pop(TRUE); if (timeout) @@ -373,10 +286,8 @@ static void start_watchdog(private_ha_segments_t *this) charon->processor->queue_job(charon->processor, (job_t*)this->job); } -/** - * Implementation of ha_segments_t.handle_status - */ -static void handle_status(private_ha_segments_t *this, segment_mask_t mask) +METHOD(ha_segments_t, handle_status, void, + private_ha_segments_t *this, segment_mask_t mask) { segment_mask_t missing; int i; @@ -431,20 +342,25 @@ static job_requeue_t send_status(private_ha_segments_t *this) } this->socket->push(this->socket, message); + message->destroy(message); /* schedule next invocation */ charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*) callback_job_create((callback_job_cb_t) send_status, this, NULL, NULL), - HEARTBEAT_DELAY); + this->heartbeat_delay); return JOB_REQUEUE_NONE; } -/** - * Implementation of ha_segments_t.destroy. - */ -static void destroy(private_ha_segments_t *this) +METHOD(ha_segments_t, is_active, bool, + private_ha_segments_t *this, u_int segment) +{ + return (this->active & SEGMENTS_BIT(segment)) != 0; +} + +METHOD(ha_segments_t, destroy, void, + private_ha_segments_t *this) { if (this->job) { @@ -460,44 +376,40 @@ static void destroy(private_ha_segments_t *this) */ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel, ha_tunnel_t *tunnel, u_int count, u_int node, - bool monitor, bool sync) + bool monitor) { - private_ha_segments_t *this = malloc_thing(private_ha_segments_t); - - memset(&this->public.listener, 0, sizeof(listener_t)); - this->public.listener.alert = (bool(*)(listener_t*, ike_sa_t *, alert_t, va_list))alert_hook; - this->public.activate = (void(*)(ha_segments_t*, u_int segment,bool))activate; - this->public.deactivate = (void(*)(ha_segments_t*, u_int segment,bool))deactivate; - this->public.resync = (void(*)(ha_segments_t*, u_int segment))resync; - this->public.handle_status = (void(*)(ha_segments_t*, segment_mask_t mask))handle_status; - this->public.destroy = (void(*)(ha_segments_t*))destroy; - - this->socket = socket; - this->tunnel = tunnel; - this->kernel = kernel; - this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); - this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT); - this->count = count; - this->node = node; - this->job = NULL; - - /* initially all segments are deactivated */ - this->active = 0; + private_ha_segments_t *this; + + INIT(this, + .public = { + .listener.alert = _alert_hook, + .activate = _activate, + .deactivate = _deactivate, + .handle_status = _handle_status, + .is_active = _is_active, + .destroy = _destroy, + }, + .socket = socket, + .tunnel = tunnel, + .kernel = kernel, + .count = count, + .node = node, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .heartbeat_delay = lib->settings->get_int(lib->settings, + "charon.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY), + .heartbeat_timeout = lib->settings->get_int(lib->settings, + "charon.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT), + ); if (monitor) { + DBG1(DBG_CFG, "starting HA heartbeat, delay %dms, timeout %dms", + this->heartbeat_delay, this->heartbeat_timeout); send_status(this); start_watchdog(this); } - if (sync) - { - /* request a resync as soon as we are up */ - charon->processor->queue_job(charon->processor, (job_t*) - callback_job_create((callback_job_cb_t)request_resync, - this, NULL, NULL)); - } - return &this->public; } diff --git a/src/libcharon/plugins/ha/ha_segments.h b/src/libcharon/plugins/ha/ha_segments.h index 6d1cd5441..eb9e5c1d5 100644 --- a/src/libcharon/plugins/ha/ha_segments.h +++ b/src/libcharon/plugins/ha/ha_segments.h @@ -68,23 +68,19 @@ struct ha_segments_t { void (*deactivate)(ha_segments_t *this, u_int segment, bool notify); /** - * Resync an active segment. - * - * To reintegrade a node into the cluster, resynchronization is reqired. - * IKE_SAs and CHILD_SAs are synced automatically during rekeying. A call - * to this method enforces a rekeying immediately sync all state of a - * segment. + * Handle a status message from the remote node. * - * @param segment segment to resync + * @param mask segments the remote node is serving actively */ - void (*resync)(ha_segments_t *this, u_int segment); + void (*handle_status)(ha_segments_t *this, segment_mask_t mask); /** - * Handle a status message from the remote node. + * Check if a given segment is currently active. * - * @param mask segments the remote node is serving actively + * @param segment segment to check + * @return TRUE if segment active */ - void (*handle_status)(ha_segments_t *this, segment_mask_t mask); + bool (*is_active)(ha_segments_t *this, u_int segment); /** * Destroy a ha_segments_t. @@ -101,11 +97,10 @@ struct ha_segments_t { * @param count number of segments the cluster uses * @param node node, currently 1 or 0 * @param monitor should we use monitoring functionality - * @param resync request a complete resync on startup * @return segment object */ ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel, ha_tunnel_t *tunnel, u_int count, u_int node, - bool monitor, bool resync); + bool monitor); -#endif /* HA_SEGMENTS_ @}*/ +#endif /** HA_SEGMENTS_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c index b84b02868..21e6eb6d5 100644 --- a/src/libcharon/plugins/ha/ha_socket.c +++ b/src/libcharon/plugins/ha/ha_socket.c @@ -58,8 +58,8 @@ struct private_ha_socket_t { * Data to pass to the send_message() callback job */ typedef struct { - ha_message_t *message; - private_ha_socket_t *this; + chunk_t chunk; + int fd; } job_data_t; /** @@ -67,7 +67,7 @@ typedef struct { */ static void job_data_destroy(job_data_t *this) { - this->message->destroy(this->message); + free(this->chunk.ptr); free(this); } @@ -76,22 +76,15 @@ static void job_data_destroy(job_data_t *this) */ static job_requeue_t send_message(job_data_t *data) { - private_ha_socket_t *this; - chunk_t chunk; - - this = data->this; - chunk = data->message->get_encoding(data->message); - if (send(this->fd, chunk.ptr, chunk.len, 0) < chunk.len) + if (send(data->fd, data->chunk.ptr, data->chunk.len, 0) < data->chunk.len) { DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno)); } return JOB_REQUEUE_NONE; } -/** - * Implementation of ha_socket_t.push - */ -static void push(private_ha_socket_t *this, ha_message_t *message) +METHOD(ha_socket_t, push, void, + private_ha_socket_t *this, ha_message_t *message) { chunk_t chunk; @@ -107,9 +100,10 @@ static void push(private_ha_socket_t *this, ha_message_t *message) /* Fallback to asynchronous transmission. This is required, as sendto() * is a blocking call if it acquires a policy. We could end up in a * deadlock, as we own an IKE_SA. */ - data = malloc_thing(job_data_t); - data->message = message; - data->this = this; + INIT(data, + .chunk = chunk_clone(chunk), + .fd = this->fd, + ); job = callback_job_create((callback_job_cb_t)send_message, data, (void*)job_data_destroy, NULL); @@ -118,13 +112,10 @@ static void push(private_ha_socket_t *this, ha_message_t *message) } DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno)); } - message->destroy(message); } -/** - * Implementation of ha_socket_t.pull - */ -static ha_message_t *pull(private_ha_socket_t *this) +METHOD(ha_socket_t, pull, ha_message_t*, + private_ha_socket_t *this) { while (TRUE) { @@ -189,10 +180,8 @@ static bool open_socket(private_ha_socket_t *this) return TRUE; } -/** - * Implementation of ha_socket_t.destroy. - */ -static void destroy(private_ha_socket_t *this) +METHOD(ha_socket_t, destroy, void, + private_ha_socket_t *this) { if (this->fd != -1) { @@ -208,15 +197,18 @@ static void destroy(private_ha_socket_t *this) */ ha_socket_t *ha_socket_create(char *local, char *remote) { - private_ha_socket_t *this = malloc_thing(private_ha_socket_t); - - this->public.push = (void(*)(ha_socket_t*, ha_message_t*))push; - this->public.pull = (ha_message_t*(*)(ha_socket_t*))pull; - this->public.destroy = (void(*)(ha_socket_t*))destroy; + private_ha_socket_t *this; - this->local = host_create_from_dns(local, 0, HA_PORT); - this->remote = host_create_from_dns(remote, 0, HA_PORT); - this->fd = -1; + INIT(this, + .public = { + .push = _push, + .pull = _pull, + .destroy = _destroy, + }, + .local = host_create_from_dns(local, 0, HA_PORT), + .remote = host_create_from_dns(remote, 0, HA_PORT), + .fd = -1, + ); if (!this->local || !this->remote) { diff --git a/src/libcharon/plugins/ha/ha_socket.h b/src/libcharon/plugins/ha/ha_socket.h index 8d398e22b..a4789a51d 100644 --- a/src/libcharon/plugins/ha/ha_socket.h +++ b/src/libcharon/plugins/ha/ha_socket.h @@ -35,7 +35,7 @@ struct ha_socket_t { /** * Push synchronization information to the responsible node. * - * @param message message to send, gets destroyed by push() + * @param message message to send */ void (*push)(ha_socket_t *this, ha_message_t *message); @@ -57,4 +57,4 @@ struct ha_socket_t { */ ha_socket_t *ha_socket_create(char *local, char *remote); -#endif /* HA_SOCKET_ @}*/ +#endif /** HA_SOCKET_ @}*/ diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index b3511e5f0..fef84a430 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -92,10 +92,8 @@ struct private_ha_tunnel_t { ha_creds_t creds; }; -/** - * Implementation of ha_tunnel_t.is_sa - */ -static bool is_sa(private_ha_tunnel_t *this, ike_sa_t *ike_sa) +METHOD(ha_tunnel_t, is_sa, bool, + private_ha_tunnel_t *this, ike_sa_t *ike_sa) { peer_cfg_t *cfg = this->backend.cfg; @@ -112,11 +110,8 @@ typedef struct { shared_key_t *key; } shared_enum_t; -/** - * Implementation of shared_enum_t.enumerate - */ -static bool shared_enumerate(shared_enum_t *this, shared_key_t **key, - id_match_t *me, id_match_t *other) +METHOD(enumerator_t, shared_enumerate, bool, + shared_enum_t *this, shared_key_t **key, id_match_t *me, id_match_t *other) { if (this->key) { @@ -135,12 +130,9 @@ static bool shared_enumerate(shared_enum_t *this, shared_key_t **key, return FALSE; } -/** - * Implements ha_creds_t.create_shared_enumerator - */ -static enumerator_t* create_shared_enumerator(ha_creds_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) +METHOD(ha_creds_t, create_shared_enumerator, enumerator_t*, + ha_creds_t *this, shared_key_type_t type, + identification_t *me, identification_t *other) { shared_enum_t *enumerator; @@ -157,28 +149,25 @@ static enumerator_t* create_shared_enumerator(ha_creds_t *this, return NULL; } - enumerator = malloc_thing(shared_enum_t); - enumerator->public.enumerate = (void*)shared_enumerate; - enumerator->public.destroy = (void*)free; - enumerator->key = this->key; + INIT(enumerator, + .public = { + .enumerate = (void*)_shared_enumerate, + .destroy = (void*)free, + }, + .key = this->key, + ); return &enumerator->public; } -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(ha_backend_t *this, - identification_t *me, identification_t *other) +METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, + ha_backend_t *this, identification_t *me, identification_t *other) { return enumerator_create_single(this->cfg, NULL); } -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(ha_backend_t *this, - host_t *me, host_t *other) +METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*, + ha_backend_t *this, host_t *me, host_t *other) { return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL); } @@ -207,11 +196,11 @@ static void setup_tunnel(private_ha_tunnel_t *this, chunk_clone(chunk_create(secret, strlen(secret)))); this->creds.public.create_private_enumerator = (void*)return_null; this->creds.public.create_cert_enumerator = (void*)return_null; - this->creds.public.create_shared_enumerator = (void*)create_shared_enumerator; + this->creds.public.create_shared_enumerator = (void*)_create_shared_enumerator; this->creds.public.create_cdp_enumerator = (void*)return_null; this->creds.public.cache_cert = (void*)nop; - charon->credentials->add_set(charon->credentials, &this->creds.public); + lib->credmgr->add_set(lib->credmgr, &this->creds.public); /* create config and backend */ ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT, @@ -233,8 +222,9 @@ static void setup_tunnel(private_ha_tunnel_t *this, identification_create_from_string(remote)); peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); - child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, - MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0); + child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT, + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535); @@ -247,8 +237,8 @@ static void setup_tunnel(private_ha_tunnel_t *this, peer_cfg->add_child_cfg(peer_cfg, child_cfg); this->backend.cfg = peer_cfg; - this->backend.public.create_peer_cfg_enumerator = (void*)create_peer_cfg_enumerator; - this->backend.public.create_ike_cfg_enumerator = (void*)create_ike_cfg_enumerator; + this->backend.public.create_peer_cfg_enumerator = (void*)_create_peer_cfg_enumerator; + this->backend.public.create_ike_cfg_enumerator = (void*)_create_ike_cfg_enumerator; this->backend.public.get_peer_cfg_by_name = (void*)return_null; charon->backends->add_backend(charon->backends, &this->backend.public); @@ -257,10 +247,8 @@ static void setup_tunnel(private_ha_tunnel_t *this, this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg); } -/** - * Implementation of ha_tunnel_t.destroy. - */ -static void destroy(private_ha_tunnel_t *this) +METHOD(ha_tunnel_t, destroy, void, + private_ha_tunnel_t *this) { if (this->backend.cfg) { @@ -269,7 +257,7 @@ static void destroy(private_ha_tunnel_t *this) } if (this->creds.key) { - charon->credentials->remove_set(charon->credentials, &this->creds.public); + lib->credmgr->remove_set(lib->credmgr, &this->creds.public); this->creds.key->destroy(this->creds.key); } this->creds.local->destroy(this->creds.local); @@ -286,10 +274,14 @@ static void destroy(private_ha_tunnel_t *this) */ ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret) { - private_ha_tunnel_t *this = malloc_thing(private_ha_tunnel_t); + private_ha_tunnel_t *this; - this->public.is_sa = (bool(*)(ha_tunnel_t*, ike_sa_t *ike_sa))is_sa; - this->public.destroy = (void(*)(ha_tunnel_t*))destroy; + INIT(this, + .public = { + .is_sa = _is_sa, + .destroy = _destroy, + }, + ); setup_tunnel(this, local, remote, secret); diff --git a/src/libcharon/plugins/ha/ha_tunnel.h b/src/libcharon/plugins/ha/ha_tunnel.h index 085fb6122..549e33055 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.h +++ b/src/libcharon/plugins/ha/ha_tunnel.h @@ -54,4 +54,4 @@ struct ha_tunnel_t { */ ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret); -#endif /* HA_TUNNEL_H_ @}*/ +#endif /** HA_TUNNEL_H_ @}*/ diff --git a/src/libcharon/plugins/kernel_klips/Makefile.in b/src/libcharon/plugins/kernel_klips/Makefile.in index f0d112a0f..9cac89ec3 100644 --- a/src/libcharon/plugins/kernel_klips/Makefile.in +++ b/src/libcharon/plugins/kernel_klips/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c index 01df4f71a..6b5aeb342 100644 --- a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c +++ b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c @@ -1690,10 +1690,11 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, - protocol_id_t protocol, u_int32_t reqid, 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) + protocol_id_t protocol, u_int32_t reqid, mark_t mark, + 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) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1849,7 +1850,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, METHOD(kernel_ipsec_t, update_sa, status_t, private_kernel_klips_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool encap, bool new_encap) + bool encap, bool new_encap, mark_t mark) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1920,14 +1921,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t, METHOD(kernel_ipsec_t, query_sa, status_t, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes) + u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) { return NOT_SUPPORTED; /* TODO */ } METHOD(kernel_ipsec_t, del_sa, status_t, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi) + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1992,8 +1993,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, - u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed) + u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -2210,7 +2211,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, METHOD(kernel_ipsec_t, query_policy, status_t, private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { #define IDLE_PREFIX "idle=" static const char *path_eroute = "/proc/net/ipsec_eroute"; @@ -2365,7 +2367,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t, METHOD(kernel_ipsec_t, del_policy, status_t, private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + bool unrouted) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg = (struct sadb_msg*)request, *out; @@ -2574,7 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void, { close(this->socket); } - if (this->socket_evnets > 0) + if (this->socket_events > 0) { close(this->socket_events); } diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in index 8c9965467..49cc895bc 100644 --- a/src/libcharon/plugins/kernel_netlink/Makefile.in +++ b/src/libcharon/plugins/kernel_netlink/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c index 1b8c1b879..019ec93f8 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -280,6 +280,9 @@ struct policy_entry_t { /** parameters of installed policy */ struct xfrm_selector sel; + /** optional mark */ + u_int32_t mark; + /** associated route installed for this policy */ route_entry_t *route; @@ -292,7 +295,8 @@ struct policy_entry_t { */ static u_int policy_hash(policy_entry_t *key) { - chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector)); + chunk_t chunk = chunk_create((void*)&key->sel, + sizeof(struct xfrm_selector) + sizeof(u_int32_t)); return chunk_hash(chunk); } @@ -301,7 +305,8 @@ static u_int policy_hash(policy_entry_t *key) */ static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key) { - return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) && + return memeq(&key->sel, &other_key->sel, + sizeof(struct xfrm_selector) + sizeof(u_int32_t)) && key->direction == other_key->direction; } @@ -917,11 +922,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, + u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark, 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 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) { netlink_buf_t request; char *alg_name; @@ -934,8 +939,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, if (ipcomp != IPCOMP_NONE && cpi != 0) { lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}}; - add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, &lft, - ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, + add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, + &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, mode, ipcomp, 0, FALSE, inbound, NULL, NULL); ipcomp = IPCOMP_NONE; /* use transport mode ESP SA, IPComp uses tunnel mode */ @@ -944,9 +949,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", - ntohl(spi), reqid); - + if (mark.value) + { + DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} " + "(mark %u/0x%8x)", ntohl(spi), reqid, mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", + ntohl(spi), reqid); + } hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; @@ -1151,6 +1163,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, if (encap) { + struct xfrm_encap_tmpl *tmpl; + rthdr->rta_type = XFRMA_ENCAP; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); @@ -1160,7 +1174,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, return FAILED; } - struct xfrm_encap_tmpl* tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr); + tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr); tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_sport = htons(src->get_port(src)); tmpl->encap_dport = htons(dst->get_port(dst)); @@ -1177,9 +1191,36 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr = XFRM_RTA_NEXT(rthdr); } + if (mark.value) + { + struct xfrm_mark *mrk; + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + rthdr = XFRM_RTA_NEXT(rthdr); + } + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { - DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); + if (mark.value) + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x " + "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); + } return FAILED; } return SUCCESS; @@ -1275,7 +1316,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this, METHOD(kernel_ipsec_t, query_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes) + u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) { netlink_buf_t request; struct nlmsghdr *out = NULL, *hdr; @@ -1285,8 +1326,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); - + if (mark.value) + { + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%8x)", + ntohl(spi), mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); + } hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_type = XFRM_MSG_GETSA; @@ -1298,6 +1346,24 @@ METHOD(kernel_ipsec_t, query_sa, status_t, sa_id->proto = proto_ike2kernel(protocol); sa_id->family = dst->get_family(dst); + if (mark.value) + { + struct xfrm_mark *mrk; + struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id); + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + } + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) { hdr = out; @@ -1313,8 +1379,20 @@ METHOD(kernel_ipsec_t, query_sa, status_t, case NLMSG_ERROR: { struct nlmsgerr *err = NLMSG_DATA(hdr); - DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)", - ntohl(spi), strerror(-err->error), -err->error); + + if (mark.value) + { + DBG1(DBG_KNL, "querying SAD entry with SPI %.8x " + "(mark %u/0x%8x) failed: %s (%d)", + ntohl(spi), mark.value, mark.mask, + strerror(-err->error), -err->error); + } + else + { + DBG1(DBG_KNL, "querying SAD entry with SPI %.8x " + "failed: %s (%d)", ntohl(spi), + strerror(-err->error), -err->error); + } break; } default: @@ -1341,7 +1419,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t, METHOD(kernel_ipsec_t, del_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi) + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark) { netlink_buf_t request; struct nlmsghdr *hdr; @@ -1350,13 +1428,20 @@ METHOD(kernel_ipsec_t, del_sa, status_t, /* if IPComp was used, we first delete the additional IPComp SA */ if (cpi) { - del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0); + del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark); } memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi)); - + if (mark.value) + { + DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%8x)", + ntohl(spi), mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi)); + } hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_type = XFRM_MSG_DELSA; @@ -1368,19 +1453,53 @@ METHOD(kernel_ipsec_t, del_sa, status_t, sa_id->proto = proto_ike2kernel(protocol); sa_id->family = dst->get_family(dst); + if (mark.value) + { + struct xfrm_mark *mrk; + struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id); + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + } + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { - DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi)); + if (mark.value) + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x " + "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi)); + } return FAILED; } - DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi)); + if (mark.value) + { + DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%8x)", + ntohl(spi), mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi)); + } return SUCCESS; } METHOD(kernel_ipsec_t, update_sa, status_t, private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool old_encap, bool new_encap) + bool old_encap, bool new_encap, mark_t mark) { netlink_buf_t request; u_char *pos; @@ -1398,7 +1517,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, if (cpi) { update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0, - src, dst, new_src, new_dst, FALSE, FALSE); + src, dst, new_src, new_dst, FALSE, FALSE, mark); } memset(&request, 0, sizeof(request)); @@ -1459,7 +1578,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, } /* delete the old SA (without affecting the IPComp SA) */ - if (del_sa(this, src, dst, spi, protocol, 0) != SUCCESS) + if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS) { DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi)); free(out); @@ -1558,8 +1677,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, - u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed) + u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed) { policy_entry_t *current, *policy; bool found = FALSE; @@ -1571,6 +1690,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy = malloc_thing(policy_entry_t); memset(policy, 0, sizeof(policy_entry_t)); policy->sel = ts2selector(src_ts, dst_ts); + policy->mark = mark.value & mark.mask; policy->direction = direction; /* find the policy, which matches EXACTLY */ @@ -1580,9 +1700,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t, { /* use existing policy */ current->refcount++; - DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " - "refcount", src_ts, dst_ts, - policy_dir_names, direction); + if (mark.value) + { + DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%8x) " + "already exists, increasing refcount", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "policy %R === %R %N " + "already exists, increasing refcount", + src_ts, dst_ts, policy_dir_names, direction); + } free(policy); policy = current; found = TRUE; @@ -1593,8 +1723,17 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy->refcount = 1; } - DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts, - policy_dir_names, direction); + if (mark.value) + { + DBG2(DBG_KNL, "adding policy %R === %R %N (mark %u/0x%8x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "adding policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + } memset(&request, 0, sizeof(request)); hdr = (struct nlmsghdr*)request; @@ -1673,6 +1812,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t, tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; tmpl->mode = mode2kernel(mode); tmpl->family = src->get_family(src); + rthdr = XFRM_RTA_NEXT(rthdr); + + if (mark.value) + { + struct xfrm_mark *mrk; + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + } if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { @@ -1741,7 +1899,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, METHOD(kernel_ipsec_t, query_policy, status_t, private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { netlink_buf_t request; struct nlmsghdr *out = NULL, *hdr; @@ -1751,9 +1910,17 @@ METHOD(kernel_ipsec_t, query_policy, status_t, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts, - policy_dir_names, direction); - + if (mark.value) + { + DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%8x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts, + policy_dir_names, direction); + } hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_type = XFRM_MSG_GETPOLICY; @@ -1763,6 +1930,25 @@ METHOD(kernel_ipsec_t, query_policy, status_t, policy_id->sel = ts2selector(src_ts, dst_ts); policy_id->dir = direction; + if (mark.value) + { + struct xfrm_mark *mrk; + struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id); + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + } + if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) { hdr = out; @@ -1816,7 +2002,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t, METHOD(kernel_ipsec_t, del_policy, status_t, private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + bool unrouted) { policy_entry_t *current, policy, *to_delete = NULL; route_entry_t *route; @@ -1824,12 +2011,22 @@ METHOD(kernel_ipsec_t, del_policy, status_t, struct nlmsghdr *hdr; struct xfrm_userpolicy_id *policy_id; - DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts, - policy_dir_names, direction); + if (mark.value) + { + DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x)", + src_ts, dst_ts, policy_dir_names, direction, + mark.value, mark.mask); + } + else + { + DBG2(DBG_KNL, "deleting policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + } /* create a policy */ memset(&policy, 0, sizeof(policy_entry_t)); policy.sel = ts2selector(src_ts, dst_ts); + policy.mark = mark.value & mark.mask; policy.direction = direction; /* find the policy */ @@ -1851,8 +2048,17 @@ METHOD(kernel_ipsec_t, del_policy, status_t, this->mutex->unlock(this->mutex); if (!to_delete) { - DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts, - dst_ts, policy_dir_names, direction); + if (mark.value) + { + DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) " + "failed, not found", src_ts, dst_ts, policy_dir_names, + direction, mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", + src_ts, dst_ts, policy_dir_names, direction); + } return NOT_FOUND; } @@ -1867,13 +2073,40 @@ METHOD(kernel_ipsec_t, del_policy, status_t, policy_id->sel = to_delete->sel; policy_id->dir = direction; + if (mark.value) + { + struct xfrm_mark *mrk; + struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id); + + rthdr->rta_type = XFRMA_MARK; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); + hdr->nlmsg_len += rthdr->rta_len; + if (hdr->nlmsg_len > sizeof(request)) + { + return FAILED; + } + + mrk = (struct xfrm_mark*)RTA_DATA(rthdr); + mrk->v = mark.value; + mrk->m = mark.mask; + } + route = to_delete->route; free(to_delete); if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { - DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts, - policy_dir_names, direction); + if (mark.value) + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N " + "(mark %u/0x%8x)", src_ts, dst_ts, policy_dir_names, + direction, mark.value, mark.mask); + } + else + { + DBG1(DBG_KNL, "unable to delete policy %R === %R %N", + src_ts, dst_ts, policy_dir_names, direction); + } return FAILED; } diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in index 2b028ba71..1dda6827b 100644 --- a/src/libcharon/plugins/kernel_pfkey/Makefile.in +++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 8a7883c8a..a64c27f6f 100644 --- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2010 Tobias Brunner * Copyright (C) 2008 Andreas Steffen * Hochschule fuer Technik Rapperswil * @@ -67,8 +67,10 @@ /** non linux specific */ #ifndef IPPROTO_COMP +#ifdef IPPROTO_IPCOMP #define IPPROTO_COMP IPPROTO_IPCOMP #endif +#endif #ifndef SADB_X_AALG_SHA2_256HMAC #define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256 @@ -600,17 +602,43 @@ static int lookup_algorithm(kernel_algorithm_t *list, int ikev2) } /** - * add a host behind a sadb_address extension + * Copy a host_t as sockaddr_t to the given memory location. Ports are + * reset to zero as per RFC 2367. + * @return the number of bytes copied */ -static void host2ext(host_t *host, struct sadb_address *ext) +static size_t hostcpy(void *dest, host_t *host) { - sockaddr_t *host_addr = host->get_sockaddr(host); + sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest; socklen_t *len = host->get_sockaddr_len(host); + memcpy(dest, addr, *len); #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN - host_addr->sa_len = *len; + dest_addr->sa_len = *len; #endif - memcpy((char*)(ext + 1), host_addr, *len); - ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len); + switch (dest_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *sin = dest; + sin->sin_port = 0; + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = dest; + sin6->sin6_port = 0; + break; + } + } + return *len; +} + +/** + * add a host behind an sadb_address extension + */ +static void host2ext(host_t *host, struct sadb_address *ext) +{ + size_t len = hostcpy(ext + 1, host); + ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + len); } /** @@ -1019,7 +1047,7 @@ static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* } #endif /*SADB_X_MIGRATE*/ -#ifdef HAVE_NATT +#ifdef SADB_X_NAT_T_NEW_MAPPING /** * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel */ @@ -1075,7 +1103,7 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* } } } -#endif /*HAVE_NATT*/ +#endif /*SADB_X_NAT_T_NEW_MAPPING*/ /** * Receives events from kernel @@ -1137,11 +1165,11 @@ static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this) process_migrate(this, msg); break; #endif /*SADB_X_MIGRATE*/ -#ifdef HAVE_NATT +#ifdef SADB_X_NAT_T_NEW_MAPPING case SADB_X_NAT_T_NEW_MAPPING: process_mapping(this, msg); break; -#endif /*HAVE_NATT*/ +#endif /*SADB_X_NAT_T_NEW_MAPPING*/ default: break; } @@ -1217,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, - protocol_id_t protocol, u_int32_t reqid, 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) + protocol_id_t protocol, u_int32_t reqid, mark_t mark, + 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) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1364,7 +1393,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, METHOD(kernel_ipsec_t, update_sa, status_t, private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, - bool encap, bool new_encap) + bool encap, bool new_encap, mark_t mark) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1497,7 +1526,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, METHOD(kernel_ipsec_t, query_sa, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes) + u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1553,7 +1582,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t, METHOD(kernel_ipsec_t, del_sa, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi) + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1604,8 +1633,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, traffic_selector_t *src_ts, traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, - u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed) + u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1679,14 +1708,10 @@ METHOD(kernel_ipsec_t, add_policy, status_t, req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; if (mode == MODE_TUNNEL) { - sockaddr_t *sa; - socklen_t sl; - sa = src->get_sockaddr(src); - sl = *src->get_sockaddr_len(src); - memcpy(req + 1, sa, sl); - sa = dst->get_sockaddr(dst); - memcpy((u_int8_t*)(req + 1) + sl, sa, sl); - req->sadb_x_ipsecrequest_len += sl * 2; + len = hostcpy(req + 1, src); + req->sadb_x_ipsecrequest_len += len; + len = hostcpy((char*)(req + 1) + len, dst); + req->sadb_x_ipsecrequest_len += len; } pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len); @@ -1771,22 +1796,30 @@ METHOD(kernel_ipsec_t, add_policy, status_t, route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)); route->prefixlen = policy->src.mask; - switch (charon->kernel_interface->add_route(charon->kernel_interface, - route->dst_net, route->prefixlen, route->gateway, - route->src_ip, route->if_name)) + if (route->if_name) + { + switch (charon->kernel_interface->add_route( + charon->kernel_interface, route->dst_net, + route->prefixlen, route->gateway, + route->src_ip, route->if_name)) + { + default: + DBG1(DBG_KNL, "unable to install source route for %H", + route->src_ip); + /* FALL */ + case ALREADY_DONE: + /* route exists, do not uninstall */ + route_entry_destroy(route); + break; + case SUCCESS: + /* cache the installed route */ + policy->route = route; + break; + } + } + else { - default: - DBG1(DBG_KNL, "unable to install source route for %H", - route->src_ip); - /* FALL */ - case ALREADY_DONE: - /* route exists, do not uninstall */ - route_entry_destroy(route); - break; - case SUCCESS: - /* cache the installed route */ - policy->route = route; - break; + route_entry_destroy(route); } } else @@ -1802,7 +1835,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, METHOD(kernel_ipsec_t, query_policy, status_t, private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1905,7 +1939,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t, METHOD(kernel_ipsec_t, del_policy, status_t, private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted) + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + bool unrouted) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in index 3a4d2c3b5..f78a97013 100644 --- a/src/libcharon/plugins/kernel_pfroute/Makefile.in +++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index 8965aff78..d049bb41b 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index c1f98f2fe..a230aa3f5 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -223,8 +223,9 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num); } - child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, - MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0); + child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, MODE_TUNNEL, + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1"); child_cfg->add_proposal(child_cfg, proposal); ts = traffic_selector_create_dynamic(0, 0, 65535); diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index 1218443cc..43c0ef009 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -34,118 +34,89 @@ struct private_load_tester_ipsec_t { u_int32_t spi; }; -/** - * Implementation of kernel_interface_t.get_spi. - */ -static status_t get_spi(private_load_tester_ipsec_t *this, - host_t *src, host_t *dst, - protocol_id_t protocol, u_int32_t reqid, - u_int32_t *spi) +METHOD(kernel_ipsec_t, get_spi, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi) { *spi = ++this->spi; return SUCCESS; } -/** - * Implementation of kernel_interface_t.get_cpi. - */ -static status_t get_cpi(private_load_tester_ipsec_t *this, - host_t *src, host_t *dst, - u_int32_t reqid, u_int16_t *cpi) +METHOD(kernel_ipsec_t, get_cpi, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t reqid, u_int16_t *cpi) { return FAILED; } -/** - * Implementation of kernel_interface_t.add_sa. - */ -static status_t add_sa(private_load_tester_ipsec_t *this, - host_t *src, host_t *dst, u_int32_t spi, - protocol_id_t protocol, u_int32_t reqid, - 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) +METHOD(kernel_ipsec_t, add_sa, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark, + 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) { return SUCCESS; } -/** - * Implementation of kernel_interface_t.update_sa. - */ -static status_t update_sa(private_load_tester_ipsec_t *this, - u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, - host_t *src, host_t *dst, - host_t *new_src, host_t *new_dst, - bool encap, bool new_encap) +METHOD(kernel_ipsec_t, update_sa, status_t, + private_load_tester_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, + u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, + host_t *new_dst, bool encap, bool new_encap, mark_t mark) { return SUCCESS; } -/** - * Implementation of kernel_interface_t.query_sa. - */ -static status_t query_sa(private_load_tester_ipsec_t *this, host_t *src, - host_t *dst, u_int32_t spi, protocol_id_t protocol, - u_int64_t *bytes) +METHOD(kernel_ipsec_t, query_sa, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) { return NOT_SUPPORTED; } -/** - * Implementation of kernel_interface_t.del_sa. - */ -static status_t del_sa(private_load_tester_ipsec_t *this, host_t *src, - host_t *dst, u_int32_t spi, protocol_id_t protocol, - u_int16_t cpi) +METHOD(kernel_ipsec_t, del_sa, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark) { return SUCCESS; } -/** - * Implementation of kernel_interface_t.add_policy. - */ -static status_t add_policy(private_load_tester_ipsec_t *this, - host_t *src, host_t *dst, - traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, - policy_dir_t direction, u_int32_t spi, - protocol_id_t protocol, u_int32_t reqid, - ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, - bool routed) +METHOD(kernel_ipsec_t, add_policy, status_t, + private_load_tester_ipsec_t *this, host_t *src, host_t *dst, + traffic_selector_t *src_ts, traffic_selector_t *dst_ts, + policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, + u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, + u_int16_t cpi, bool routed) { return SUCCESS; } -/** - * Implementation of kernel_interface_t.query_policy. - */ -static status_t query_policy(private_load_tester_ipsec_t *this, - traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, - policy_dir_t direction, u_int32_t *use_time) +METHOD(kernel_ipsec_t, query_policy, status_t, + private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + u_int32_t *use_time) { *use_time = time_monotonic(NULL); return SUCCESS; } -/** - * Implementation of kernel_interface_t.del_policy. - */ -static status_t del_policy(private_load_tester_ipsec_t *this, - traffic_selector_t *src_ts, - traffic_selector_t *dst_ts, - policy_dir_t direction, bool unrouted) +METHOD(kernel_ipsec_t, del_policy, status_t, + private_load_tester_ipsec_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, + bool unrouted) { return SUCCESS; } -/** - * Implementation of kernel_interface_t.destroy. - */ -static void destroy(private_load_tester_ipsec_t *this) +METHOD(kernel_ipsec_t, bypass_socket, bool, + private_load_tester_ipsec_t *this, int fd, int family) +{ + return TRUE; +} + +METHOD(kernel_ipsec_t, destroy, void, + private_load_tester_ipsec_t *this) { free(this); } @@ -155,21 +126,26 @@ static void destroy(private_load_tester_ipsec_t *this) */ load_tester_ipsec_t *load_tester_ipsec_create() { - private_load_tester_ipsec_t *this = malloc_thing(private_load_tester_ipsec_t); - - /* public functions */ - this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; - this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi; - this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa; - this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa; - this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa; - this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa; - this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t *this,host_t *, host_t *,traffic_selector_t *,traffic_selector_t *,policy_dir_t, u_int32_t,protocol_id_t, u_int32_t,ipsec_mode_t, u_int16_t, u_int16_t,bool))add_policy; - this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy; - this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy; - this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy; - - this->spi = 0; + private_load_tester_ipsec_t *this; + + INIT(this, + .public = { + .interface = { + .get_spi = _get_spi, + .get_cpi = _get_cpi, + .add_sa = _add_sa, + .update_sa = _update_sa, + .query_sa = _query_sa, + .del_sa = _del_sa, + .add_policy = _add_policy, + .query_policy = _query_policy, + .del_policy = _del_policy, + .bypass_socket = _bypass_socket, + .destroy = _destroy, + }, + }, + .spi = 0, + ); return &this->public; } diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index 46145b803..15dbccb00 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -158,7 +158,7 @@ static void destroy(private_load_tester_plugin_t *this) charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface, (kernel_ipsec_constructor_t)load_tester_ipsec_create); charon->backends->remove_backend(charon->backends, &this->config->backend); - charon->credentials->remove_set(charon->credentials, &this->creds->credential_set); + lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set); charon->bus->remove_listener(charon->bus, &this->listener->listener); this->config->destroy(this->config); this->creds->destroy(this->creds); @@ -209,7 +209,7 @@ plugin_t *load_tester_plugin_create() this->creds = load_tester_creds_create(); this->listener = load_tester_listener_create(shutdown_on); charon->backends->add_backend(charon->backends, &this->config->backend); - charon->credentials->add_set(charon->credentials, &this->creds->credential_set); + 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, diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index 539890ec3..c26d325a9 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index e355d55f7..6cbaf36f2 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -181,8 +181,9 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam identification_create_from_encoding(ID_KEY_ID, other)); peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); - child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, - MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0); + child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); @@ -260,7 +261,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) this->current->add_auth_cfg(this->current, auth, FALSE); child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0); + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); diff --git a/src/libcharon/plugins/medcli/medcli_plugin.c b/src/libcharon/plugins/medcli/medcli_plugin.c index 397168d46..6befbf440 100644 --- a/src/libcharon/plugins/medcli/medcli_plugin.c +++ b/src/libcharon/plugins/medcli/medcli_plugin.c @@ -61,7 +61,7 @@ static void destroy(private_medcli_plugin_t *this) { charon->bus->remove_listener(charon->bus, &this->listener->listener); charon->backends->remove_backend(charon->backends, &this->config->backend); - charon->credentials->remove_set(charon->credentials, &this->creds->set); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); this->listener->destroy(this->listener); this->config->destroy(this->config); this->creds->destroy(this->creds); @@ -100,7 +100,7 @@ plugin_t *medcli_plugin_create() this->config = medcli_config_create(this->db); this->listener = medcli_listener_create(this->db); - charon->credentials->add_set(charon->credentials, &this->creds->set); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); charon->backends->add_backend(charon->backends, &this->config->backend); charon->bus->add_listener(charon->bus, &this->listener->listener); diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index a103a1340..4dc9c00d0 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.c b/src/libcharon/plugins/medsrv/medsrv_plugin.c index 262d26d6b..c150346cb 100644 --- a/src/libcharon/plugins/medsrv/medsrv_plugin.c +++ b/src/libcharon/plugins/medsrv/medsrv_plugin.c @@ -54,7 +54,7 @@ struct private_medsrv_plugin_t { static void destroy(private_medsrv_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); - charon->credentials->remove_set(charon->credentials, &this->creds->set); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); this->config->destroy(this->config); this->creds->destroy(this->creds); this->db->destroy(this->db); @@ -91,7 +91,7 @@ plugin_t *medsrv_plugin_create() this->creds = medsrv_creds_create(this->db); this->config = medsrv_config_create(this->db); - charon->credentials->add_set(charon->credentials, &this->creds->set); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); charon->backends->add_backend(charon->backends, &this->config->backend); return &this->public.plugin; diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in index c7f288f54..1b3e4c5a6 100644 --- a/src/libcharon/plugins/nm/Makefile.in +++ b/src/libcharon/plugins/nm/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c index 6087f6589..250e6f7f9 100644 --- a/src/libcharon/plugins/nm/nm_plugin.c +++ b/src/libcharon/plugins/nm/nm_plugin.c @@ -84,7 +84,7 @@ static void destroy(private_nm_plugin_t *this) { g_object_unref(this->plugin); } - charon->credentials->remove_set(charon->credentials, &this->creds->set); + lib->credmgr->remove_set(lib->credmgr, &this->creds->set); hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); this->creds->destroy(this->creds); this->handler->destroy(this->handler); @@ -110,7 +110,7 @@ plugin_t *nm_plugin_create() this->creds = nm_creds_create(); this->handler = nm_handler_create(); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); - charon->credentials->add_set(charon->credentials, &this->creds->set); + lib->credmgr->add_set(lib->credmgr, &this->creds->set); this->plugin = nm_strongswan_plugin_new(this->creds, this->handler); if (!this->plugin) { diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index cdf7dc962..07318bbbf 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -444,7 +444,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, child_cfg = child_cfg_create(priv->name, &lifetime, NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ - ACTION_NONE, ACTION_NONE, ipcomp, 0); + ACTION_NONE, ACTION_NONE, ipcomp, 0, 0, + NULL, NULL); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); ts = traffic_selector_create_dynamic(0, 0, 65535); child_cfg->add_traffic_selector(child_cfg, TRUE, ts); diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am deleted file mode 100644 index f8830d42e..000000000 --- a/src/libcharon/plugins/resolve/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = -rdynamic \ - -DRESOLV_CONF=\"${resolv_conf}\" - -if MONOLITHIC -noinst_LTLIBRARIES = libstrongswan-resolve.la -else -plugin_LTLIBRARIES = libstrongswan-resolve.la -endif - -libstrongswan_resolve_la_SOURCES = \ - resolve_plugin.h resolve_plugin.c \ - resolve_handler.h resolve_handler.c - -libstrongswan_resolve_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c deleted file mode 100644 index 714c751a6..000000000 --- a/src/libcharon/plugins/resolve/resolve_handler.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "resolve_handler.h" - -#include <unistd.h> - -#include <daemon.h> -#include <threading/mutex.h> - -typedef struct private_resolve_handler_t private_resolve_handler_t; - -/** - * Private data of an resolve_handler_t object. - */ -struct private_resolve_handler_t { - - /** - * Public resolve_handler_t interface. - */ - resolve_handler_t public; - - /** - * resolv.conf file to use - */ - char *file; - - /** - * Mutex to access file exclusively - */ - mutex_t *mutex; -}; - -/** - * Implementation of attribute_handler_t.handle - */ -static bool handle(private_resolve_handler_t *this, identification_t *server, - configuration_attribute_type_t type, chunk_t data) -{ - FILE *in, *out; - char buf[1024]; - host_t *addr; - size_t len; - bool handled = FALSE; - - switch (type) - { - case INTERNAL_IP4_DNS: - addr = host_create_from_chunk(AF_INET, data, 0); - break; - case INTERNAL_IP6_DNS: - addr = host_create_from_chunk(AF_INET6, data, 0); - break; - default: - return FALSE; - } - - if (!addr || addr->is_anyaddr(addr)) - { - DESTROY_IF(addr); - return FALSE; - } - this->mutex->lock(this->mutex); - - in = fopen(this->file, "r"); - /* allows us to stream from in to out */ - unlink(this->file); - out = fopen(this->file, "w"); - if (out) - { - fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server); - DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file); - handled = TRUE; - - /* copy rest of the file */ - if (in) - { - while ((len = fread(buf, 1, sizeof(buf), in))) - { - ignore_result(fwrite(buf, 1, len, out)); - } - } - fclose(out); - } - if (in) - { - fclose(in); - } - this->mutex->unlock(this->mutex); - addr->destroy(addr); - - if (!handled) - { - DBG1(DBG_IKE, "adding DNS server failed", this->file); - } - return handled; -} - -/** - * Implementation of attribute_handler_t.release - */ -static void release(private_resolve_handler_t *this, identification_t *server, - configuration_attribute_type_t type, chunk_t data) -{ - FILE *in, *out; - char line[1024], matcher[512], *pos; - host_t *addr; - int family; - - switch (type) - { - case INTERNAL_IP4_DNS: - family = AF_INET; - break; - case INTERNAL_IP6_DNS: - family = AF_INET6; - break; - default: - return; - } - - this->mutex->lock(this->mutex); - - in = fopen(this->file, "r"); - if (in) - { - /* allows us to stream from in to out */ - unlink(this->file); - out = fopen(this->file, "w"); - if (out) - { - addr = host_create_from_chunk(family, data, 0); - snprintf(matcher, sizeof(matcher), - "nameserver %H # by strongSwan, from %Y\n", - addr, server); - - /* copy all, but matching line */ - while ((pos = fgets(line, sizeof(line), in))) - { - if (strneq(line, matcher, strlen(matcher))) - { - DBG1(DBG_IKE, "removing DNS server %H from %s", - addr, this->file); - } - else - { - fputs(line, out); - } - } - addr->destroy(addr); - fclose(out); - } - fclose(in); - } - - this->mutex->unlock(this->mutex); -} - -/** - * Attribute enumerator implementation - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** virtual IP we are requesting */ - host_t *vip; -} attribute_enumerator_t; - -/** - * Implementation of create_attribute_enumerator().enumerate() - */ -static bool attribute_enumerate(attribute_enumerator_t *this, - configuration_attribute_type_t *type, chunk_t *data) -{ - switch (this->vip->get_family(this->vip)) - { - case AF_INET: - *type = INTERNAL_IP4_DNS; - break; - case AF_INET6: - *type = INTERNAL_IP6_DNS; - break; - default: - return FALSE; - } - *data = chunk_empty; - /* enumerate only once */ - this->public.enumerate = (void*)return_false; - return TRUE; -} - -/** - * Implementation of attribute_handler_t.create_attribute_enumerator - */ -static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this, - identification_t *server, host_t *vip) -{ - if (vip) - { - attribute_enumerator_t *enumerator; - - enumerator = malloc_thing(attribute_enumerator_t); - enumerator->public.enumerate = (void*)attribute_enumerate; - enumerator->public.destroy = (void*)free; - enumerator->vip = vip; - - return &enumerator->public; - } - return enumerator_create_empty(); -} - -/** - * Implementation of resolve_handler_t.destroy. - */ -static void destroy(private_resolve_handler_t *this) -{ - this->mutex->destroy(this->mutex); - free(this); -} - -/** - * See header - */ -resolve_handler_t *resolve_handler_create() -{ - private_resolve_handler_t *this = malloc_thing(private_resolve_handler_t); - - this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle; - this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release; - this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator; - this->public.destroy = (void(*)(resolve_handler_t*))destroy; - - this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); - this->file = lib->settings->get_str(lib->settings, - "charon.plugins.resolve.file", RESOLV_CONF); - - return &this->public; -} - diff --git a/src/libcharon/plugins/resolve/resolve_plugin.c b/src/libcharon/plugins/resolve/resolve_plugin.c deleted file mode 100644 index 502129593..000000000 --- a/src/libcharon/plugins/resolve/resolve_plugin.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "resolve_plugin.h" -#include "resolve_handler.h" - -#include <hydra.h> - -typedef struct private_resolve_plugin_t private_resolve_plugin_t; - -/** - * private data of resolve plugin - */ -struct private_resolve_plugin_t { - - /** - * implements plugin interface - */ - resolve_plugin_t public; - - /** - * The registerd DNS attribute handler - */ - resolve_handler_t *handler; -}; - -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_resolve_plugin_t *this) -{ - hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); - this->handler->destroy(this->handler); - free(this); -} - -/* - * see header file - */ -plugin_t *resolve_plugin_create() -{ - private_resolve_plugin_t *this = malloc_thing(private_resolve_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - this->handler = resolve_handler_create(); - hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); - - return &this->public.plugin; -} - diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index b88283f38..35fb8367f 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index 03c438acd..df63d862e 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 3a5fb3778..8a3a15188 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in index 65ad6a7a9..32bd9e0a1 100644 --- a/src/libcharon/plugins/socket_raw/Makefile.in +++ b/src/libcharon/plugins/socket_raw/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index e0155fa87..166870421 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -538,11 +538,12 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) /* Destination Port must be either port or natt_port */ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 5, 12), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 6, 14), /* port */ - /* IKE version must be 2.0 */ + /* IKE version must be 2.x */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 10), + BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 11), /* packet length is length in IKEv2 header + ip header + udp header */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + IKE_LENGTH_OFFSET), BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN), @@ -550,10 +551,11 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) /* natt_port */ /* nat-t: check for marker */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 5), - /* nat-t: IKE version must be 2.0 */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 6), + /* nat-t: IKE version must be 2.x */ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + MARKER_LEN + IKE_VERSION_OFFSET), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3), + BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 3), /* nat-t: packet length is length in IKEv2 header + ip header + udp header + non esp marker */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + MARKER_LEN + IKE_LENGTH_OFFSET), BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN + MARKER_LEN), diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index 5803dc898..e32dc7b57 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index 23366898a..a47d93f7b 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -134,7 +134,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e) .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter } }; child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode, - dpd, close, ipcomp, 0); + dpd, close, ipcomp, 0, 0, NULL, NULL); /* TODO: read proposal from db */ child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); add_traffic_selectors(this, child_cfg, id); diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c index e2d2d63b3..7b0a198d1 100644 --- a/src/libcharon/plugins/sql/sql_plugin.c +++ b/src/libcharon/plugins/sql/sql_plugin.c @@ -59,7 +59,7 @@ struct private_sql_plugin_t { static void destroy(private_sql_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); - charon->credentials->remove_set(charon->credentials, &this->cred->set); + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); charon->bus->remove_listener(charon->bus, &this->logger->listener); this->config->destroy(this->config); this->cred->destroy(this->cred); @@ -99,7 +99,7 @@ plugin_t *sql_plugin_create() this->logger = sql_logger_create(this->db); charon->backends->add_backend(charon->backends, &this->config->backend); - charon->credentials->add_set(charon->credentials, &this->cred->set); + lib->credmgr->add_set(lib->credmgr, &this->cred->set); charon->bus->add_listener(charon->bus, &this->logger->listener); return &this->public.plugin; diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index 8815ba741..e094200ca 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c index 49146f18b..9a3ae0ab9 100644 --- a/src/libcharon/plugins/stroke/stroke_ca.c +++ b/src/libcharon/plugins/stroke/stroke_ca.c @@ -306,7 +306,8 @@ static void del(private_stroke_ca_t *this, stroke_msg_t *msg) return; } ca_section_destroy(ca); - /* TODO: flush cached certs */ + + lib->credmgr->flush_cache(lib->credmgr, CERT_ANY); } /** @@ -356,12 +357,16 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer { if (section->certuribase && cert->issued_by(cert, section->cert)) { - chunk_t hash, encoded = cert->get_encoding(cert); - hasher->allocate_hash(hasher, encoded, &hash); - section->hashes->insert_last(section->hashes, - identification_create_from_encoding(ID_KEY_ID, hash)); - chunk_free(&hash); - chunk_free(&encoded); + chunk_t hash, encoded; + + if (cert->get_encoding(cert, CERT_ASN1_DER, &encoded)) + { + hasher->allocate_hash(hasher, encoded, &hash); + section->hashes->insert_last(section->hashes, + identification_create_from_encoding(ID_KEY_ID, hash)); + chunk_free(&hash); + chunk_free(&encoded); + } break; } } @@ -400,11 +405,11 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) /* list authkey and keyid */ if (public) { - if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) + if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk)) { fprintf(out, " authkey: %#B\n", &chunk); } - if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &chunk)) + if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &chunk)) { fprintf(out, " keyid: %#B\n", &chunk); } diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index bbc1e7a31..617069432 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -399,8 +399,8 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, if (ca) { identity = identification_create_from_string(ca); - certificate = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, identity, TRUE); + certificate = lib->credmgr->get_cert(lib->credmgr, CERT_X509, + KEY_ANY, identity, TRUE); identity->destroy(identity); if (certificate) { @@ -413,7 +413,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } } - /* AC groups */ + /* groups */ if (end->groups) { enumerator_t *enumerator; @@ -422,9 +422,8 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, enumerator = enumerator_create_token(end->groups, ",", " "); while (enumerator->enumerate(enumerator, &group)) { - identity = identification_create_from_encoding(ID_IETF_ATTR_STRING, - chunk_create(group, strlen(group))); - cfg->add(cfg, AUTH_RULE_AC_GROUP, identity); + cfg->add(cfg, AUTH_RULE_GROUP, + identification_create_from_string(group)); } enumerator->destroy(enumerator); } @@ -769,6 +768,14 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, .jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100 } }; + mark_t mark_in = { + .value = msg->add_conn.mark_in.value, + .mask = msg->add_conn.mark_in.mask + }; + mark_t mark_out = { + .value = msg->add_conn.mark_out.value, + .mask = msg->add_conn.mark_out.mask + }; switch (msg->add_conn.dpd.action) { /* map startes magic values to our action type */ @@ -787,7 +794,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this, msg->add_conn.name, &lifetime, msg->add_conn.me.updown, msg->add_conn.me.hostaccess, msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp, - msg->add_conn.inactivity); + msg->add_conn.inactivity, msg->add_conn.reqid, + &mark_in, &mark_out); child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode, msg->add_conn.install_policy); add_ts(this, &msg->add_conn.me, child_cfg, TRUE); diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index a03aef697..f64421551 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -186,6 +186,11 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o } else { + if (!pos) + { + DBG1(DBG_CFG, "error parsing string"); + return; + } if (*(pos + 1) == '*') { /* is name[*] */ all = TRUE; diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index e0a5210a9..2816b9bb2 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -378,7 +378,7 @@ static bool add_crl(private_stroke_cred_t *this, crl_t* crl) } if (found) { - new = cert->is_newer(cert, current); + new = crl_is_newer(crl, crl_c); if (new) { this->certs->remove_at(this->certs, enumerator); @@ -587,9 +587,11 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert) snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex); free(hex.ptr); - chunk = cert->get_encoding(cert); - chunk_write(chunk, buf, "crl", 022, TRUE); - free(chunk.ptr); + if (cert->get_encoding(cert, CERT_ASN1_DER, &chunk)) + { + chunk_write(chunk, buf, "crl", 022, TRUE); + free(chunk.ptr); + } } } } diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index c2a98da33..a6de35466 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -17,6 +17,10 @@ #include <time.h> +#ifdef HAVE_MALLINFO +#include <malloc.h> +#endif /* HAVE_MALLINFO */ + #include <daemon.h> #include <utils/linked_list.h> #include <credentials/certificates/x509.h> @@ -55,6 +59,33 @@ struct private_stroke_list_t { }; /** + * Log tasks of a specific queue to out + */ +static void log_task_q(FILE *out, ike_sa_t *ike_sa, task_queue_t q, char *name) +{ + enumerator_t *enumerator; + bool has = FALSE; + task_t *task; + + enumerator = ike_sa->create_task_enumerator(ike_sa, q); + while (enumerator->enumerate(enumerator, &task)) + { + if (!has) + { + fprintf(out, "%12s[%d]: Tasks %s: ", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa), name); + has = TRUE; + } + fprintf(out, "%N ", task_type_names, task->get_type(task)); + } + enumerator->destroy(enumerator); + if (has) + { + fprintf(out, "\n"); + } +} + +/** * log an IKE_SA to out */ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) @@ -140,6 +171,10 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all) ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), buf+4); } + + log_task_q(out, ike_sa, TASK_QUEUE_QUEUED, "queued"); + log_task_q(out, ike_sa, TASK_QUEUE_ACTIVE, "active"); + log_task_q(out, ike_sa, TASK_QUEUE_PASSIVE, "passive"); } } @@ -342,7 +377,7 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local) rules = auth->create_enumerator(auth); while (rules->enumerate(rules, &rule, &id)) { - if (rule == AUTH_RULE_AC_GROUP) + if (rule == AUTH_RULE_GROUP) { fprintf(out, "%12s: group: %Y\n", name, id); } @@ -373,12 +408,19 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo u_int32_t dpd; time_t since, now; u_int size, online, offline; - now = time_monotonic(NULL); since = time(NULL) - (now - this->uptime); fprintf(out, "Status of IKEv2 charon daemon (strongSwan "VERSION"):\n"); fprintf(out, " uptime: %V, since %T\n", &now, &this->uptime, &since, FALSE); +#ifdef HAVE_MALLINFO + { + struct mallinfo mi = mallinfo(); + + fprintf(out, " malloc: sbrk %d, mmap %d, used %d, free %d\n", + mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks); + } +#endif /* HAVE_MALLINFO */ fprintf(out, " worker threads: %d idle of %d,", charon->processor->get_idle_threads(charon->processor), charon->processor->get_total_threads(charon->processor)); @@ -534,9 +576,8 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo static linked_list_t* create_unique_cert_list(certificate_type_t type) { linked_list_t *list = linked_list_create(); - enumerator_t *enumerator = charon->credentials->create_cert_enumerator( - charon->credentials, type, KEY_ANY, - NULL, FALSE); + enumerator_t *enumerator = lib->credmgr->create_cert_enumerator( + lib->credmgr, type, KEY_ANY, NULL, FALSE); certificate_t *cert; while (enumerator->enumerate(enumerator, (void**)&cert)) @@ -585,11 +626,11 @@ static void list_public_key(public_key_t *public, FILE *out) identification_t *id; auth_cfg_t *auth; - if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid)) + if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid)) { id = identification_create_from_encoding(ID_KEY_ID, keyid); auth = auth_cfg_create(); - private = charon->credentials->get_private(charon->credentials, + private = lib->credmgr->get_private(lib->credmgr, public->get_type(public), id, auth); auth->destroy(auth); id->destroy(id); @@ -599,11 +640,11 @@ static void list_public_key(public_key_t *public, FILE *out) key_type_names, public->get_type(public), public->get_keysize(public) * 8, private ? ", has private key" : ""); - if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid)) { fprintf(out, " keyid: %#B\n", &keyid); } - if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid)) + if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid)) { fprintf(out, " subjkey: %#B\n", &keyid); } diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 56c18da38..18afa5af4 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -344,8 +344,7 @@ static void stroke_purge(private_stroke_socket_t *this, { if (msg->purge.flags & PURGE_OCSP) { - charon->credentials->flush_cache(charon->credentials, - CERT_X509_OCSP_RESPONSE); + lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE); } if (msg->purge.flags & PURGE_IKE) { @@ -622,8 +621,8 @@ static bool open_socket(private_stroke_socket_t *this) static void destroy(private_stroke_socket_t *this) { this->job->cancel(this->job); - charon->credentials->remove_set(charon->credentials, &this->ca->set); - charon->credentials->remove_set(charon->credentials, &this->cred->set); + lib->credmgr->remove_set(lib->credmgr, &this->ca->set); + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); charon->backends->remove_backend(charon->backends, &this->config->backend); hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider); this->cred->destroy(this->cred); @@ -657,8 +656,8 @@ stroke_socket_t *stroke_socket_create() this->control = stroke_control_create(); this->list = stroke_list_create(this->attribute); - charon->credentials->add_set(charon->credentials, &this->ca->set); - charon->credentials->add_set(charon->credentials, &this->cred->set); + lib->credmgr->add_set(lib->credmgr, &this->ca->set); + lib->credmgr->add_set(lib->credmgr, &this->cred->set); charon->backends->add_backend(charon->backends, &this->config->backend); hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider); diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index c10829bb3..934ab6080 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index bd58afbf0..ddddae782 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -196,7 +196,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg) this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE); child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, FALSE, 0); + ACTION_NONE, ACTION_NONE, FALSE, 0, 0, + NULL, NULL); child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP)); child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net)); diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c index 742fcf4d0..4790ef4e7 100644 --- a/src/libcharon/plugins/uci/uci_plugin.c +++ b/src/libcharon/plugins/uci/uci_plugin.c @@ -64,7 +64,7 @@ struct private_uci_plugin_t { static void destroy(private_uci_plugin_t *this) { charon->backends->remove_backend(charon->backends, &this->config->backend); - charon->credentials->remove_set(charon->credentials, &this->creds->credential_set); + lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set); this->config->destroy(this->config); this->creds->destroy(this->creds); this->parser->destroy(this->parser); @@ -86,7 +86,7 @@ plugin_t *uci_plugin_create() this->creds = uci_creds_create(this->parser); this->control = uci_control_create(); charon->backends->add_backend(charon->backends, &this->config->backend); - charon->credentials->add_set(charon->credentials, &this->creds->credential_set); + lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set); return &this->public.plugin; } diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am index e27d1f859..c46d2b85d 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.am +++ b/src/libcharon/plugins/unit_tester/Makefile.am @@ -24,6 +24,7 @@ libstrongswan_unit_tester_la_SOURCES = \ tests/test_chunk.c \ tests/test_pool.c \ tests/test_agent.c \ - tests/test_id.c + tests/test_id.c \ + tests/test_hashtable.c libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in index 6ca43a38f..47850c1c5 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.in +++ b/src/libcharon/plugins/unit_tester/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -78,7 +78,7 @@ am_libstrongswan_unit_tester_la_OBJECTS = unit_tester.lo \ test_enumerator.lo test_auth_info.lo test_curl.lo \ test_mysql.lo test_sqlite.lo test_mutex.lo test_rsa_gen.lo \ test_cert.lo test_med_db.lo test_chunk.lo test_pool.lo \ - test_agent.lo test_id.lo + test_agent.lo test_id.lo test_hashtable.lo libstrongswan_unit_tester_la_OBJECTS = \ $(am_libstrongswan_unit_tester_la_OBJECTS) libstrongswan_unit_tester_la_LINK = $(LIBTOOL) --tag=CC \ @@ -281,7 +281,8 @@ libstrongswan_unit_tester_la_SOURCES = \ tests/test_chunk.c \ tests/test_pool.c \ tests/test_agent.c \ - tests/test_id.c + tests/test_id.c \ + tests/test_hashtable.c libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version all: all-am @@ -373,6 +374,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_chunk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_curl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_enumerator.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_hashtable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_id.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_med_db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mutex.Plo@am__quote@ @@ -494,6 +496,13 @@ test_id.lo: tests/test_id.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_id.lo `test -f 'tests/test_id.c' || echo '$(srcdir)/'`tests/test_id.c +test_hashtable.lo: tests/test_hashtable.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_hashtable.lo -MD -MP -MF $(DEPDIR)/test_hashtable.Tpo -c -o test_hashtable.lo `test -f 'tests/test_hashtable.c' || echo '$(srcdir)/'`tests/test_hashtable.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_hashtable.Tpo $(DEPDIR)/test_hashtable.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_hashtable.c' object='test_hashtable.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_hashtable.lo `test -f 'tests/test_hashtable.c' || echo '$(srcdir)/'`tests/test_hashtable.c + mostlyclean-libtool: -rm -f *.lo diff --git a/src/libcharon/plugins/unit_tester/tests.h b/src/libcharon/plugins/unit_tester/tests.h index 96313d390..cd38c8a99 100644 --- a/src/libcharon/plugins/unit_tester/tests.h +++ b/src/libcharon/plugins/unit_tester/tests.h @@ -19,6 +19,7 @@ */ DEFINE_TEST("linked_list_t->remove()", test_list_remove, FALSE) +DEFINE_TEST("hashtable_t->remove_at()", test_hashtable_remove_at, FALSE) DEFINE_TEST("simple enumerator", test_enumerate, FALSE) DEFINE_TEST("nested enumerator", test_enumerate_nested, FALSE) DEFINE_TEST("filtered enumerator", test_enumerate_filtered, FALSE) diff --git a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c index d6abe7a05..c250c356f 100644 --- a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c +++ b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c @@ -15,7 +15,7 @@ #include <daemon.h> #include <library.h> -#include <config/auth_cfg.h> +#include <credentials/auth_cfg.h> static chunk_t certchunk = chunk_from_chars( diff --git a/src/libcharon/plugins/unit_tester/tests/test_hashtable.c b/src/libcharon/plugins/unit_tester/tests/test_hashtable.c new file mode 100644 index 000000000..bd79e12f7 --- /dev/null +++ b/src/libcharon/plugins/unit_tester/tests/test_hashtable.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 <library.h> +#include <utils/hashtable.h> + +static u_int hash(char *key) +{ + return chunk_hash(chunk_create(key, strlen(key))); +} + +static u_int equals(char *key1, char *key2) +{ + return streq(key1, key2); +} + +/** + * Test the remove_at method + */ +bool test_hashtable_remove_at() +{ + char *k1 = "key1", *k2 = "key2", *k3 = "key3", *key; + char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value; + enumerator_t *enumerator; + hashtable_t *ht = hashtable_create((hashtable_hash_t)hash, + (hashtable_equals_t)equals, 0); + + ht->put(ht, k1, v1); + ht->put(ht, k2, v2); + ht->put(ht, k3, v3); + + if (ht->get_count(ht) != 3) + { + return FALSE; + } + + enumerator = ht->create_enumerator(ht); + while (enumerator->enumerate(enumerator, &key, &value)) + { + if (streq(key, k2)) + { + ht->remove_at(ht, enumerator); + } + } + enumerator->destroy(enumerator); + + if (ht->get_count(ht) != 2) + { + return FALSE; + } + + if (ht->get(ht, k1) == NULL || + ht->get(ht, k3) == NULL) + { + return FALSE; + } + + if (ht->get(ht, k2) != NULL) + { + return FALSE; + } + + ht->put(ht, k2, v2); + + if (ht->get_count(ht) != 3) + { + return FALSE; + } + + if (ht->get(ht, k1) == NULL || + ht->get(ht, k2) == NULL || + ht->get(ht, k3) == NULL) + { + return FALSE; + } + + enumerator = ht->create_enumerator(ht); + while (enumerator->enumerate(enumerator, &key, &value)) + { + ht->remove_at(ht, enumerator); + } + enumerator->destroy(enumerator); + + if (ht->get_count(ht) != 0) + { + return FALSE; + } + + if (ht->get(ht, k1) != NULL || + ht->get(ht, k2) != NULL || + ht->get(ht, k3) != NULL) + { + return FALSE; + } + + ht->destroy(ht); + + return TRUE; +} diff --git a/src/libcharon/plugins/unit_tester/tests/test_med_db.c b/src/libcharon/plugins/unit_tester/tests/test_med_db.c index 7fd78b0bc..ae1d08e15 100644 --- a/src/libcharon/plugins/unit_tester/tests/test_med_db.c +++ b/src/libcharon/plugins/unit_tester/tests/test_med_db.c @@ -37,11 +37,11 @@ bool test_med_db() bool good = FALSE; id = identification_create_from_encoding(ID_KEY_ID, keyid); - enumerator = charon->credentials->create_public_enumerator( - charon->credentials, KEY_ANY, id, NULL); + enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, + KEY_ANY, id, NULL); while (enumerator->enumerate(enumerator, &public, &auth)) { - good = public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &found); + good = public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &found); if (good) { good = chunk_equals(id->get_encoding(id), found); diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index d3c509a32..ce233ad04 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c index 5a6746f92..ea4a792c2 100644 --- a/src/libcharon/plugins/updown/updown_listener.c +++ b/src/libcharon/plugins/updown/updown_listener.c @@ -115,7 +115,8 @@ METHOD(listener_t, child_updown, bool, { char command[1024]; char *my_client, *other_client, *my_client_mask, *other_client_mask; - char *pos, *virtual_ip, *iface; + char *pos, *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc; + mark_t mark; bool is_host, is_ipv6; FILE *shell; @@ -160,6 +161,61 @@ METHOD(listener_t, child_updown, bool, } } + /* check for the presence of an inbound mark */ + mark = config->get_mark(config, TRUE); + if (mark.value) + { + if (asprintf(&mark_in, "PLUTO_MARK_IN='%u/0x%08x' ", + mark.value, mark.mask ) < 0) + { + mark_in = NULL; + } + } + else + { + if (asprintf(&mark_in, "") < 0) + { + mark_in = NULL; + } + } + + /* check for the presence of an outbound mark */ + mark = config->get_mark(config, FALSE); + if (mark.value) + { + if (asprintf(&mark_out, "PLUTO_MARK_OUT='%u/0x%08x' ", + mark.value, mark.mask ) < 0) + { + mark_out = NULL; + } + } + else + { + if (asprintf(&mark_out, "") < 0) + { + mark_out = NULL; + } + } + + /* check for a NAT condition causing ESP_IN_UDP encapsulation */ + if (ike_sa->has_condition(ike_sa, COND_NAT_ANY)) + { + if (asprintf(&udp_enc, "PLUTO_UDP_ENC='%u' ", + other->get_port(other)) < 0) + { + udp_enc = NULL; + } + + } + else + { + if (asprintf(&udp_enc, "") < 0) + { + udp_enc = NULL; + } + + } + if (up) { iface = charon->kernel_interface->get_interface( @@ -205,6 +261,9 @@ METHOD(listener_t, child_updown, bool, "PLUTO_PEER_PROTOCOL='%u' " "%s" "%s" + "%s" + "%s" + "%s" "%s", up ? "up" : "down", is_host ? "-host" : "-client", @@ -223,11 +282,17 @@ METHOD(listener_t, child_updown, bool, other_ts->get_from_port(other_ts), other_ts->get_protocol(other_ts), virtual_ip, + mark_in, + mark_out, + udp_enc, config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "", script); free(my_client); free(other_client); free(virtual_ip); + free(mark_in); + free(mark_out); + free(udp_enc); free(iface); DBG3(DBG_CHD, "running updown script: %s", command); @@ -283,7 +348,9 @@ updown_listener_t *updown_listener_create() INIT(this, .public = { - .listener.child_updown = _child_updown, + .listener = { + .child_updown = _child_updown, + }, .destroy = _destroy, }, .iface_cache = linked_list_create(), diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c index 13586a23e..cd340e53e 100644 --- a/src/libcharon/sa/authenticators/authenticator.c +++ b/src/libcharon/sa/authenticators/authenticator.c @@ -34,13 +34,6 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS, "ECDSA-521 signature"); ENUM_END(auth_method_names, AUTH_ECDSA_521); -ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP, - "any", - "public key", - "pre-shared key", - "EAP", -); - /** * Described in header. */ diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h index fff91ed34..89178b5cf 100644 --- a/src/libcharon/sa/authenticators/authenticator.h +++ b/src/libcharon/sa/authenticators/authenticator.h @@ -24,11 +24,10 @@ #define AUTHENTICATOR_H_ typedef enum auth_method_t auth_method_t; -typedef enum auth_class_t auth_class_t; typedef struct authenticator_t authenticator_t; #include <library.h> -#include <config/auth_cfg.h> +#include <credentials/auth_cfg.h> #include <sa/ike_sa.h> /** @@ -76,27 +75,6 @@ enum auth_method_t { extern enum_name_t *auth_method_names; /** - * Class of authentication to use. This is different to auth_method_t in that - * it does not specify a method, but a class of acceptable methods. The found - * certificate finally dictates wich method is used. - */ -enum auth_class_t { - /** any class acceptable */ - AUTH_CLASS_ANY = 0, - /** authentication using public keys (RSA, ECDSA) */ - AUTH_CLASS_PUBKEY = 1, - /** authentication using a pre-shared secrets */ - AUTH_CLASS_PSK = 2, - /** authentication using EAP */ - AUTH_CLASS_EAP = 3, -}; - -/** - * enum strings for auth_class_t - */ -extern enum_name_t *auth_class_names; - -/** * Authenticator interface implemented by the various authenticators. * * An authenticator implementation handles AUTH and EAP payloads. Received diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c index 91fa5305f..ad7b92cfa 100644 --- a/src/libcharon/sa/authenticators/eap/eap_method.c +++ b/src/libcharon/sa/authenticators/eap/eap_method.c @@ -15,44 +15,6 @@ #include "eap_method.h" -ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC, - "EAP_IDENTITY", - "EAP_NOTIFICATION", - "EAP_NAK", - "EAP_MD5", - "EAP_OTP", - "EAP_GTC"); -ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC, - "EAP_SIM"); -ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM, - "EAP_AKA"); -ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA, - "EAP_MSCHAPV2"); -ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2, - "EAP_RADIUS", - "EAP_EXPANDED", - "EAP_EXPERIMENTAL"); -ENUM_END(eap_type_names, EAP_EXPERIMENTAL); - -ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC, - "ID", - "NTF", - "NAK", - "MD5", - "OTP", - "GTC"); -ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_GTC, - "SIM"); -ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM, - "AKA"); -ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA, - "MSCHAPV2"); -ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2, - "RAD", - "EXP", - "XP"); -ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL); - /* * See header */ diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h index 4cab84535..df354edb4 100644 --- a/src/libcharon/sa/authenticators/eap/eap_method.h +++ b/src/libcharon/sa/authenticators/eap/eap_method.h @@ -23,7 +23,6 @@ typedef struct eap_method_t eap_method_t; typedef enum eap_role_t eap_role_t; -typedef enum eap_type_t eap_type_t; typedef enum eap_code_t eap_code_t; #include <library.h> @@ -43,35 +42,6 @@ enum eap_role_t { extern enum_name_t *eap_role_names; /** - * EAP types, defines the EAP method implementation - */ -enum eap_type_t { - EAP_IDENTITY = 1, - EAP_NOTIFICATION = 2, - EAP_NAK = 3, - EAP_MD5 = 4, - EAP_OTP = 5, - EAP_GTC = 6, - EAP_SIM = 18, - EAP_AKA = 23, - EAP_MSCHAPV2 = 26, - /** not a method, but an implementation providing different methods */ - EAP_RADIUS = 253, - EAP_EXPANDED = 254, - EAP_EXPERIMENTAL = 255, -}; - -/** - * enum names for eap_type_t. - */ -extern enum_name_t *eap_type_names; - -/** - * short string enum names for eap_type_t. - */ -extern enum_name_t *eap_type_short_names; - -/** * Lookup the EAP method type from a string. * * @param name EAP method name (such as "md5", "aka") diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c index 4617c4d8d..3c0f3c358 100644 --- a/src/libcharon/sa/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/authenticators/eap_authenticator.c @@ -140,17 +140,26 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, id = auth->get(auth, AUTH_RULE_EAP_IDENTITY); if (id) { - this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER); - if (this->method) + if (id->get_type(id) == ID_ANY) { - if (this->method->initiate(this->method, &out) == NEED_MORE) + this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER); + if (this->method) { - DBG1(DBG_IKE, "initiating EAP-Identity request"); - return out; + if (this->method->initiate(this->method, &out) == NEED_MORE) + { + DBG1(DBG_IKE, "initiating EAP-Identity request"); + return out; + } + this->method->destroy(this->method); } - this->method->destroy(this->method); + DBG1(DBG_IKE, "EAP-Identity request configured, " + "but not supported"); + } + else + { + DBG1(DBG_IKE, "using configured EAP-Identity %Y", id); + this->eap_identity = id->clone(id); } - DBG1(DBG_IKE, "EAP-Identity request configured, but not supported"); } } /* invoke real EAP method */ @@ -220,7 +229,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, eap_type_t type, received_type; u_int32_t vendor, received_vendor; eap_payload_t *out; - auth_cfg_t *cfg; if (in->get_code(in) != EAP_RESPONSE) { @@ -283,12 +291,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this, } this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED, TRUE); - cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); - cfg->add(cfg, AUTH_RULE_EAP_TYPE, type); - if (vendor) - { - cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor); - } this->eap_complete = TRUE; return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in)); case FAILED: diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c index 67197d690..e69f30dcf 100644 --- a/src/libcharon/sa/authenticators/psk_authenticator.c +++ b/src/libcharon/sa/authenticators/psk_authenticator.c @@ -63,8 +63,7 @@ static status_t build(private_psk_authenticator_t *this, message_t *message) other_id = this->ike_sa->get_other_id(this->ike_sa); DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N", my_id, auth_method_names, AUTH_PSK); - key = charon->credentials->get_shared(charon->credentials, SHARED_IKE, - my_id, other_id); + key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id, other_id); if (key == NULL) { DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id); @@ -107,8 +106,8 @@ static status_t process(private_psk_authenticator_t *this, message_t *message) recv_auth_data = auth_payload->get_data(auth_payload); my_id = this->ike_sa->get_my_id(this->ike_sa); other_id = this->ike_sa->get_other_id(this->ike_sa); - enumerator = charon->credentials->create_shared_enumerator( - charon->credentials, SHARED_IKE, my_id, other_id); + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_IKE, my_id, other_id); while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL)) { keys_found++; diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c index f1dca2702..3c67f6db6 100644 --- a/src/libcharon/sa/authenticators/pubkey_authenticator.c +++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c @@ -65,8 +65,7 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message) id = this->ike_sa->get_my_id(this->ike_sa); auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - private = charon->credentials->get_private(charon->credentials, KEY_ANY, - id, auth); + private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth); if (private == NULL) { DBG1(DBG_IKE, "no private key found for '%Y'", id); @@ -178,8 +177,8 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init, this->nonce, id); auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); - enumerator = charon->credentials->create_public_enumerator( - charon->credentials, key_type, id, auth); + enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, + key_type, id, auth); while (enumerator->enumerate(enumerator, &public, ¤t_auth)) { if (public->verify(public, scheme, octets, auth_data)) diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index 3fdfb51ad..bd41cba56 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -98,6 +98,16 @@ struct private_child_sa_t { u_int32_t reqid; /** + * inbound mark used for this child_sa + */ + mark_t mark_in; + + /** + * outbound mark used for this child_sa + */ + mark_t mark_out; + + /** * absolute time when rekeying is scheduled */ time_t rekey_time; @@ -128,6 +138,16 @@ struct private_child_sa_t { ipsec_mode_t mode; /** + * Action to enforce if peer closes the CHILD_SA + */ + action_t close_action; + + /** + * Action to enforce if peer is considered dead + */ + action_t dpd_action; + + /** * selected proposal */ proposal_t *proposal; @@ -272,6 +292,38 @@ static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp) } /** + * Implementation of child_sa_t.set_close_action. + */ +static void set_close_action(private_child_sa_t *this, action_t action) +{ + this->close_action = action; +} + +/** + * Implementation of child_sa_t.get_close_action. + */ +static action_t get_close_action(private_child_sa_t *this) +{ + return this->close_action; +} + +/** + * Implementation of child_sa_t.set_dpd_action. + */ +static void set_dpd_action(private_child_sa_t *this, action_t action) +{ + this->dpd_action = action; +} + +/** + * Implementation of child_sa_t.get_dpd_action. + */ +static action_t get_dpd_action(private_child_sa_t *this) +{ + return this->dpd_action; +} + +/** * Implementation of child_sa_t.get_proposal */ static proposal_t* get_proposal(private_child_sa_t *this) @@ -389,10 +441,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound) { if (this->my_spi) { - status = charon->kernel_interface->query_sa( - charon->kernel_interface, + status = charon->kernel_interface->query_sa(charon->kernel_interface, this->other_addr, this->my_addr, - this->my_spi, this->protocol, &bytes); + this->my_spi, this->protocol, + this->mark_in, &bytes); if (status == SUCCESS) { if (bytes > this->my_usebytes) @@ -408,10 +460,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound) { if (this->other_spi) { - status = charon->kernel_interface->query_sa( - charon->kernel_interface, + status = charon->kernel_interface->query_sa(charon->kernel_interface, this->my_addr, this->other_addr, - this->other_spi, this->protocol, &bytes); + this->other_spi, this->protocol, + this->mark_out, &bytes); if (status == SUCCESS) { if (bytes > this->other_usebytes) @@ -443,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound) if (inbound) { if (charon->kernel_interface->query_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_IN, &in) == SUCCESS) + other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS) { last_use = max(last_use, in); } if (this->mode != MODE_TRANSPORT) { if (charon->kernel_interface->query_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS) + other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS) { last_use = max(last_use, fwd); } @@ -459,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound) else { if (charon->kernel_interface->query_policy(charon->kernel_interface, - my_ts, other_ts, POLICY_OUT, &out) == SUCCESS) + my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS) { last_use = max(last_use, out); } @@ -623,9 +675,10 @@ static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ, } status = charon->kernel_interface->add_sa(charon->kernel_interface, - src, dst, spi, this->protocol, this->reqid, lifetime, - enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi, - this->encap, update, src_ts, dst_ts); + src, dst, spi, this->protocol, this->reqid, + inbound ? this->mark_in : this->mark_out, + lifetime, enc_alg, encr, int_alg, integ, this->mode, + this->ipcomp, cpi, this->encap, update, src_ts, dst_ts); free(lifetime); @@ -666,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this, /* install 3 policies: out, in and forward */ status |= charon->kernel_interface->add_policy(charon->kernel_interface, this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT, - this->other_spi, this->protocol, this->reqid, this->mode, - this->ipcomp, this->other_cpi, routed); + this->other_spi, this->protocol, this->reqid, this->mark_out, + this->mode, this->ipcomp, this->other_cpi, routed); status |= charon->kernel_interface->add_policy(charon->kernel_interface, this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN, - this->my_spi, this->protocol, this->reqid, this->mode, - this->ipcomp, this->my_cpi, routed); + this->my_spi, this->protocol, this->reqid, this->mark_in, + this->mode, this->ipcomp, this->my_cpi, routed); if (this->mode != MODE_TRANSPORT) { status |= charon->kernel_interface->add_policy(charon->kernel_interface, this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD, - this->my_spi, this->protocol, this->reqid, this->mode, - this->ipcomp, this->my_cpi, routed); + this->my_spi, this->protocol, this->reqid, this->mark_in, + this->mode, this->ipcomp, this->my_cpi, routed); } if (status != SUCCESS) @@ -726,7 +779,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other, this->my_spi, this->protocol, this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0, this->other_addr, this->my_addr, other, me, - this->encap, encap) == NOT_SUPPORTED) + this->encap, encap, this->mark_in) == NOT_SUPPORTED) { return NOT_SUPPORTED; } @@ -739,7 +792,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other, this->other_spi, this->protocol, this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0, this->my_addr, this->other_addr, me, other, - this->encap, encap) == NOT_SUPPORTED) + this->encap, encap, this->mark_out) == NOT_SUPPORTED) { return NOT_SUPPORTED; } @@ -761,13 +814,13 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other, { /* remove old policies first */ charon->kernel_interface->del_policy(charon->kernel_interface, - my_ts, other_ts, POLICY_OUT, FALSE); + my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE); charon->kernel_interface->del_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_IN, FALSE); + other_ts, my_ts, POLICY_IN, this->mark_in, FALSE); if (this->mode != MODE_TRANSPORT) { charon->kernel_interface->del_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_FWD, FALSE); + other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE); } /* check whether we have to update a "dynamic" traffic selector */ @@ -793,18 +846,18 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other, /* reinstall updated policies */ charon->kernel_interface->add_policy(charon->kernel_interface, me, other, my_ts, other_ts, POLICY_OUT, this->other_spi, - this->protocol, this->reqid, this->mode, this->ipcomp, - this->other_cpi, FALSE); + this->protocol, this->reqid, this->mark_out, this->mode, + this->ipcomp, this->other_cpi, FALSE); charon->kernel_interface->add_policy(charon->kernel_interface, other, me, other_ts, my_ts, POLICY_IN, this->my_spi, - this->protocol, this->reqid, this->mode, this->ipcomp, - this->my_cpi, FALSE); + this->protocol, this->reqid, this->mark_in, this->mode, + this->ipcomp, this->my_cpi, FALSE); if (this->mode != MODE_TRANSPORT) { charon->kernel_interface->add_policy(charon->kernel_interface, other, me, other_ts, my_ts, POLICY_FWD, this->my_spi, - this->protocol, this->reqid, this->mode, this->ipcomp, - this->my_cpi, FALSE); + this->protocol, this->reqid, this->mark_in, this->mode, + this->ipcomp, this->my_cpi, FALSE); } } enumerator->destroy(enumerator); @@ -854,13 +907,13 @@ static void destroy(private_child_sa_t *this) } charon->kernel_interface->del_sa(charon->kernel_interface, this->other_addr, this->my_addr, this->my_spi, - this->protocol, this->my_cpi); + this->protocol, this->my_cpi, this->mark_in); } if (this->other_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, this->my_addr, this->other_addr, this->other_spi, - this->protocol, this->other_cpi); + this->protocol, this->other_cpi, this->mark_out); } if (this->config->install_policy(this->config)) @@ -870,13 +923,13 @@ static void destroy(private_child_sa_t *this) while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) { charon->kernel_interface->del_policy(charon->kernel_interface, - my_ts, other_ts, POLICY_OUT, unrouted); + my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted); charon->kernel_interface->del_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_IN, unrouted); + other_ts, my_ts, POLICY_IN, this->mark_in, unrouted); if (this->mode != MODE_TRANSPORT) { charon->kernel_interface->del_policy(charon->kernel_interface, - other_ts, my_ts, POLICY_FWD, unrouted); + other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted); } } enumerator->destroy(enumerator); @@ -919,6 +972,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->public.has_encap = (bool(*)(child_sa_t*))has_encap; this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp; this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp; + this->public.get_close_action = (action_t(*)(child_sa_t*))get_close_action; + this->public.set_close_action = (void(*)(child_sa_t*,action_t))set_close_action; + this->public.get_dpd_action = (action_t(*)(child_sa_t*))get_dpd_action; + this->public.set_dpd_action = (void(*)(child_sa_t*,action_t))set_dpd_action; this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi; this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi; this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install; @@ -942,17 +999,26 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->other_usetime = 0; this->my_usebytes = 0; this->other_usebytes = 0; - /* reuse old reqid if we are rekeying an existing CHILD_SA */ - this->reqid = rekey ? rekey : ++reqid; this->my_ts = linked_list_create(); this->other_ts = linked_list_create(); this->protocol = PROTO_NONE; this->mode = MODE_TUNNEL; + this->close_action = config->get_close_action(config); + this->dpd_action = config->get_dpd_action(config); this->proposal = NULL; this->rekey_time = 0; this->expire_time = 0; this->config = config; config->get_ref(config); + this->reqid = config->get_reqid(config); + this->mark_in = config->get_mark(config, TRUE); + this->mark_out = config->get_mark(config, FALSE); + + if (!this->reqid) + { + /* reuse old reqid if we are rekeying an existing CHILD_SA */ + this->reqid = rekey ? rekey : ++reqid; + } /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */ if (config->get_mode(config) == MODE_TRANSPORT && diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h index e6c603504..95bc297b0 100644 --- a/src/libcharon/sa/child_sa.h +++ b/src/libcharon/sa/child_sa.h @@ -208,6 +208,34 @@ struct child_sa_t { void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp); /** + * Get the action to enforce if the remote peer closes the CHILD_SA. + * + * @return close action + */ + action_t (*get_close_action)(child_sa_t *this); + + /** + * Override the close action specified by the CHILD_SA config. + * + * @param close action to enforce + */ + void (*set_close_action)(child_sa_t *this, action_t action); + + /** + * Get the action to enforce if the peer is considered dead. + * + * @return dpd action + */ + action_t (*get_dpd_action)(child_sa_t *this); + + /** + * Override the DPD action specified by the CHILD_SA config. + * + * @param close action to enforce + */ + void (*set_dpd_action)(child_sa_t *this, action_t action); + + /** * Get the selected proposal. * * @return selected proposal diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 023f0749f..7536662ca 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -287,18 +287,14 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound) return use_time; } -/** - * Implementation of ike_sa_t.get_unique_id - */ -static u_int32_t get_unique_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_unique_id, u_int32_t, + private_ike_sa_t *this) { return this->unique_id; } -/** - * Implementation of ike_sa_t.get_name. - */ -static char *get_name(private_ike_sa_t *this) +METHOD(ike_sa_t, get_name, char*, + private_ike_sa_t *this) { if (this->peer_cfg) { @@ -307,10 +303,8 @@ static char *get_name(private_ike_sa_t *this) return "(unnamed)"; } -/** - * Implementation of ike_sa_t.get_statistic. - */ -static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind) +METHOD(ike_sa_t, get_statistic, u_int32_t, + private_ike_sa_t *this, statistic_t kind) { if (kind < STAT_MAX) { @@ -319,52 +313,40 @@ static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind) return 0; } -/** - * Implementation of ike_sa_t.get_my_host. - */ -static host_t *get_my_host(private_ike_sa_t *this) +METHOD(ike_sa_t, get_my_host, host_t*, + private_ike_sa_t *this) { return this->my_host; } -/** - * Implementation of ike_sa_t.set_my_host. - */ -static void set_my_host(private_ike_sa_t *this, host_t *me) +METHOD(ike_sa_t, set_my_host, void, + private_ike_sa_t *this, host_t *me) { DESTROY_IF(this->my_host); this->my_host = me; } -/** - * Implementation of ike_sa_t.get_other_host. - */ -static host_t *get_other_host(private_ike_sa_t *this) +METHOD(ike_sa_t, get_other_host, host_t*, + private_ike_sa_t *this) { return this->other_host; } -/** - * Implementation of ike_sa_t.set_other_host. - */ -static void set_other_host(private_ike_sa_t *this, host_t *other) +METHOD(ike_sa_t, set_other_host, void, + private_ike_sa_t *this, host_t *other) { DESTROY_IF(this->other_host); this->other_host = other; } -/** - * Implementation of ike_sa_t.get_peer_cfg - */ -static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this) +METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*, + private_ike_sa_t *this) { return this->peer_cfg; } -/** - * Implementation of ike_sa_t.set_peer_cfg - */ -static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) +METHOD(ike_sa_t, set_peer_cfg, void, + private_ike_sa_t *this, peer_cfg_t *peer_cfg) { DESTROY_IF(this->peer_cfg); peer_cfg->get_ref(peer_cfg); @@ -377,10 +359,8 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) } } -/** - * Implementation of ike_sa_t.get_auth_cfg - */ -static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local) +METHOD(ike_sa_t, get_auth_cfg, auth_cfg_t*, + private_ike_sa_t *this, bool local) { if (local) { @@ -389,10 +369,8 @@ static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local) return this->other_auth; } -/** - * Implementation of ike_sa_t.add_auth_cfg - */ -static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg) +METHOD(ike_sa_t, add_auth_cfg, void, + private_ike_sa_t *this, bool local, auth_cfg_t *cfg) { if (local) { @@ -404,11 +382,8 @@ static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg) } } -/** - * Implementation of ike_sa_t.create_auth_cfg_enumerator - */ -static enumerator_t* create_auth_cfg_enumerator(private_ike_sa_t *this, - bool local) +METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*, + private_ike_sa_t *this, bool local) { if (local) { @@ -424,42 +399,33 @@ static void flush_auth_cfgs(private_ike_sa_t *this) { auth_cfg_t *cfg; - if (lib->settings->get_bool(lib->settings, "charon.flush_auth_cfg", FALSE)) + while (this->my_auths->remove_last(this->my_auths, + (void**)&cfg) == SUCCESS) { - while (this->my_auths->remove_last(this->my_auths, - (void**)&cfg) == SUCCESS) - { - cfg->destroy(cfg); - } - while (this->other_auths->remove_last(this->other_auths, - (void**)&cfg) == SUCCESS) - { - cfg->destroy(cfg); - } + cfg->destroy(cfg); + } + while (this->other_auths->remove_last(this->other_auths, + (void**)&cfg) == SUCCESS) + { + cfg->destroy(cfg); } } -/** - * Implementation of ike_sa_t.get_proposal - */ -static proposal_t* get_proposal(private_ike_sa_t *this) +METHOD(ike_sa_t, get_proposal, proposal_t*, + private_ike_sa_t *this) { return this->proposal; } -/** - * Implementation of ike_sa_t.set_proposal - */ -static void set_proposal(private_ike_sa_t *this, proposal_t *proposal) +METHOD(ike_sa_t, set_proposal, void, + private_ike_sa_t *this, proposal_t *proposal) { DESTROY_IF(this->proposal); this->proposal = proposal->clone(proposal); } -/** - * Implementation of ike_sa_t.set_message_id - */ -static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid) +METHOD(ike_sa_t, set_message_id, void, + private_ike_sa_t *this, bool initiate, u_int32_t mid) { if (initiate) { @@ -471,10 +437,8 @@ static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid) } } -/** - * Implementation of ike_sa_t.send_keepalive - */ -static void send_keepalive(private_ike_sa_t *this) +METHOD(ike_sa_t, send_keepalive, void, + private_ike_sa_t *this) { send_keepalive_job_t *job; time_t last_out, now, diff; @@ -510,52 +474,39 @@ static void send_keepalive(private_ike_sa_t *this) this->keepalive_interval - diff); } -/** - * Implementation of ike_sa_t.get_ike_cfg - */ -static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this) +METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*, + private_ike_sa_t *this) { return this->ike_cfg; } -/** - * Implementation of ike_sa_t.set_ike_cfg - */ -static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg) +METHOD(ike_sa_t, set_ike_cfg, void, + private_ike_sa_t *this, ike_cfg_t *ike_cfg) { ike_cfg->get_ref(ike_cfg); this->ike_cfg = ike_cfg; } -/** - * Implementation of ike_sa_t.enable_extension. - */ -static void enable_extension(private_ike_sa_t *this, ike_extension_t extension) +METHOD(ike_sa_t, enable_extension, void, + private_ike_sa_t *this, ike_extension_t extension) { this->extensions |= extension; } -/** - * Implementation of ike_sa_t.has_extension. - */ -static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension) +METHOD(ike_sa_t, supports_extension, bool, + private_ike_sa_t *this, ike_extension_t extension) { return (this->extensions & extension) != FALSE; } -/** - * Implementation of ike_sa_t.has_condition. - */ -static bool has_condition(private_ike_sa_t *this, ike_condition_t condition) +METHOD(ike_sa_t, has_condition, bool, + private_ike_sa_t *this, ike_condition_t condition) { return (this->conditions & condition) != FALSE; } -/** - * Implementation of ike_sa_t.enable_condition. - */ -static void set_condition(private_ike_sa_t *this, ike_condition_t condition, - bool enable) +METHOD(ike_sa_t, set_condition, void, + private_ike_sa_t *this, ike_condition_t condition, bool enable) { if (has_condition(this, condition) != enable) { @@ -601,10 +552,8 @@ static void set_condition(private_ike_sa_t *this, ike_condition_t condition, } } -/** - * Implementation of ike_sa_t.send_dpd - */ -static status_t send_dpd(private_ike_sa_t *this) +METHOD(ike_sa_t, send_dpd, status_t, + private_ike_sa_t *this) { job_t *job; time_t diff, delay; @@ -660,18 +609,14 @@ static status_t send_dpd(private_ike_sa_t *this) return SUCCESS; } -/** - * Implementation of ike_sa_t.get_state. - */ -static ike_sa_state_t get_state(private_ike_sa_t *this) +METHOD(ike_sa_t, get_state, ike_sa_state_t, + private_ike_sa_t *this) { return this->state; } -/** - * Implementation of ike_sa_t.set_state. - */ -static void set_state(private_ike_sa_t *this, ike_sa_state_t state) +METHOD(ike_sa_t, set_state, void, + private_ike_sa_t *this, ike_sa_state_t state) { DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N", get_name(this), this->unique_id, @@ -754,10 +699,8 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state) this->state = state; } -/** - * Implementation of ike_sa_t.reset - */ -static void reset(private_ike_sa_t *this) +METHOD(ike_sa_t, reset, void, + private_ike_sa_t *this) { /* the responder ID is reset, as peer may choose another one */ if (this->ike_sa_id->is_initiator(this->ike_sa_id)) @@ -767,21 +710,22 @@ static void reset(private_ike_sa_t *this) set_state(this, IKE_CREATED); + flush_auth_cfgs(this); + + this->keymat->destroy(this->keymat); + this->keymat = keymat_create(this->ike_sa_id->is_initiator(this->ike_sa_id)); + this->task_manager->reset(this->task_manager, 0, 0); } -/** - * Implementation of ike_sa_t.get_keymat - */ -static keymat_t* get_keymat(private_ike_sa_t *this) +METHOD(ike_sa_t, get_keymat, keymat_t*, + private_ike_sa_t *this) { return this->keymat; } -/** - * Implementation of ike_sa_t.set_virtual_ip - */ -static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip) +METHOD(ike_sa_t, set_virtual_ip, void, + private_ike_sa_t *this, bool local, host_t *ip) { if (local) { @@ -811,10 +755,8 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip) } } -/** - * Implementation of ike_sa_t.get_virtual_ip - */ -static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) +METHOD(ike_sa_t, get_virtual_ip, host_t*, + private_ike_sa_t *this, bool local) { if (local) { @@ -826,27 +768,21 @@ static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) } } -/** - * Implementation of ike_sa_t.add_additional_address. - */ -static void add_additional_address(private_ike_sa_t *this, host_t *host) +METHOD(ike_sa_t, add_additional_address, void, + private_ike_sa_t *this, host_t *host) { this->additional_addresses->insert_last(this->additional_addresses, host); } -/** - * Implementation of ike_sa_t.create_additional_address_iterator. - */ -static iterator_t* create_additional_address_iterator(private_ike_sa_t *this) +METHOD(ike_sa_t, create_additional_address_iterator, iterator_t*, + private_ike_sa_t *this) { return this->additional_addresses->create_iterator( this->additional_addresses, TRUE); } -/** - * Implementation of ike_sa_t.has_mapping_changed - */ -static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash) +METHOD(ike_sa_t, has_mapping_changed, bool, + private_ike_sa_t *this, chunk_t hash) { if (this->nat_detection_dest.ptr == NULL) { @@ -862,26 +798,20 @@ static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash) return TRUE; } -/** - * Implementation of ike_sa_t.set_pending_updates. - */ -static void set_pending_updates(private_ike_sa_t *this, u_int32_t updates) +METHOD(ike_sa_t, set_pending_updates, void, + private_ike_sa_t *this, u_int32_t updates) { this->pending_updates = updates; } -/** - * Implementation of ike_sa_t.get_pending_updates. - */ -static u_int32_t get_pending_updates(private_ike_sa_t *this) +METHOD(ike_sa_t, get_pending_updates, u_int32_t, + private_ike_sa_t *this) { return this->pending_updates; } -/** - * Update hosts, as addresses may change (NAT) - */ -static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) +METHOD(ike_sa_t, update_hosts, void, + private_ike_sa_t *this, host_t *me, host_t *other) { bool update = FALSE; @@ -946,11 +876,8 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) } } -/** - * Implementation of ike_sa_t.generate - */ -static status_t generate_message(private_ike_sa_t *this, message_t *message, - packet_t **packet) +METHOD(ike_sa_t, generate_message, status_t, + private_ike_sa_t *this, message_t *message, packet_t **packet) { this->stats[STAT_OUTBOUND] = time_monotonic(NULL); message->set_ike_sa_id(message, this->ike_sa_id); @@ -994,10 +921,8 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request, response->destroy(response); } -/** - * Implementation of ike_sa_t.set_kmaddress. - */ -static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote) +METHOD(ike_sa_t, set_kmaddress, void, + private_ike_sa_t *this, host_t *local, host_t *remote) { DESTROY_IF(this->local_host); DESTROY_IF(this->remote_host); @@ -1006,46 +931,35 @@ static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote) } #ifdef ME -/** - * Implementation of ike_sa_t.act_as_mediation_server. - */ -static void act_as_mediation_server(private_ike_sa_t *this) +METHOD(ike_sa_t, act_as_mediation_server, void, + private_ike_sa_t *this) { charon->mediation_manager->update_sa_id(charon->mediation_manager, this->other_id, this->ike_sa_id); this->is_mediation_server = TRUE; } -/** - * Implementation of ike_sa_t.get_server_reflexive_host. - */ -static host_t *get_server_reflexive_host(private_ike_sa_t *this) +METHOD(ike_sa_t, get_server_reflexive_host, host_t*, + private_ike_sa_t *this) { return this->server_reflexive_host; } -/** - * Implementation of ike_sa_t.set_server_reflexive_host. - */ -static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host) +METHOD(ike_sa_t, set_server_reflexive_host, void, + private_ike_sa_t *this, host_t *host) { DESTROY_IF(this->server_reflexive_host); this->server_reflexive_host = host; } -/** - * Implementation of ike_sa_t.get_connect_id. - */ -static chunk_t get_connect_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_connect_id, chunk_t, + private_ike_sa_t *this) { return this->connect_id; } -/** - * Implementation of ike_sa_t.respond - */ -static status_t respond(private_ike_sa_t *this, identification_t *peer_id, - chunk_t connect_id) +METHOD(ike_sa_t, respond, status_t, + private_ike_sa_t *this, identification_t *peer_id, chunk_t connect_id) { ike_me_t *task = ike_me_create(&this->public, TRUE); task->respond(task, peer_id, connect_id); @@ -1053,10 +967,8 @@ static status_t respond(private_ike_sa_t *this, identification_t *peer_id, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.callback - */ -static status_t callback(private_ike_sa_t *this, identification_t *peer_id) +METHOD(ike_sa_t, callback, status_t, + private_ike_sa_t *this, identification_t *peer_id) { ike_me_t *task = ike_me_create(&this->public, TRUE); task->callback(task, peer_id); @@ -1064,12 +976,9 @@ static status_t callback(private_ike_sa_t *this, identification_t *peer_id) return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.relay - */ -static status_t relay(private_ike_sa_t *this, identification_t *requester, - chunk_t connect_id, chunk_t connect_key, - linked_list_t *endpoints, bool response) +METHOD(ike_sa_t, relay, status_t, + private_ike_sa_t *this, identification_t *requester, chunk_t connect_id, + chunk_t connect_key, linked_list_t *endpoints, bool response) { ike_me_t *task = ike_me_create(&this->public, TRUE); task->relay(task, requester, connect_id, connect_key, endpoints, response); @@ -1077,11 +986,8 @@ static status_t relay(private_ike_sa_t *this, identification_t *requester, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.initiate_mediation - */ -static status_t initiate_mediation(private_ike_sa_t *this, - peer_cfg_t *mediated_cfg) +METHOD(ike_sa_t, initiate_mediation, status_t, + private_ike_sa_t *this, peer_cfg_t *mediated_cfg) { ike_me_t *task = ike_me_create(&this->public, TRUE); task->connect(task, mediated_cfg->get_peer_id(mediated_cfg)); @@ -1089,11 +995,8 @@ static status_t initiate_mediation(private_ike_sa_t *this, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.initiate_mediated - */ -static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, - host_t *other, chunk_t connect_id) +METHOD(ike_sa_t, initiate_mediated, status_t, + private_ike_sa_t *this, host_t *me, host_t *other, chunk_t connect_id) { set_my_host(this, me->clone(me)); set_other_host(this, other->clone(other)); @@ -1166,12 +1069,9 @@ static void resolve_hosts(private_ike_sa_t *this) } } -/** - * Implementation of ike_sa_t.initiate - */ -static status_t initiate(private_ike_sa_t *this, - child_cfg_t *child_cfg, u_int32_t reqid, - traffic_selector_t *tsi, traffic_selector_t *tsr) +METHOD(ike_sa_t, initiate, status_t, + private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid, + traffic_selector_t *tsi, traffic_selector_t *tsr) { task_t *task; @@ -1259,10 +1159,8 @@ static status_t initiate(private_ike_sa_t *this, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.process_message. - */ -static status_t process_message(private_ike_sa_t *this, message_t *message) +METHOD(ike_sa_t, process_message, status_t, + private_ike_sa_t *this, message_t *message) { status_t status; bool is_request; @@ -1367,7 +1265,9 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) } status = this->task_manager->process_message(this->task_manager, message); if (message->get_exchange_type(message) == IKE_AUTH && - this->state == IKE_ESTABLISHED) + this->state == IKE_ESTABLISHED && + lib->settings->get_bool(lib->settings, + "charon.flush_auth_cfg", FALSE)) { /* authentication completed */ flush_auth_cfgs(this); } @@ -1375,43 +1275,33 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) return status; } -/** - * Implementation of ike_sa_t.get_id. - */ -static ike_sa_id_t* get_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_id, ike_sa_id_t*, + private_ike_sa_t *this) { return this->ike_sa_id; } -/** - * Implementation of ike_sa_t.get_my_id. - */ -static identification_t* get_my_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_my_id, identification_t*, + private_ike_sa_t *this) { return this->my_id; } -/** - * Implementation of ike_sa_t.set_my_id. - */ -static void set_my_id(private_ike_sa_t *this, identification_t *me) +METHOD(ike_sa_t, set_my_id, void, + private_ike_sa_t *this, identification_t *me) { DESTROY_IF(this->my_id); this->my_id = me; } -/** - * Implementation of ike_sa_t.get_other_id. - */ -static identification_t* get_other_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_other_id, identification_t*, + private_ike_sa_t *this) { return this->other_id; } -/** - * Implementation of ike_sa_t.get_other_eap_id. - */ -static identification_t* get_other_eap_id(private_ike_sa_t *this) +METHOD(ike_sa_t, get_other_eap_id, identification_t*, + private_ike_sa_t *this) { identification_t *id = NULL, *current; enumerator_t *enumerator; @@ -1440,28 +1330,21 @@ static identification_t* get_other_eap_id(private_ike_sa_t *this) return this->other_id; } -/** - * Implementation of ike_sa_t.set_other_id. - */ -static void set_other_id(private_ike_sa_t *this, identification_t *other) +METHOD(ike_sa_t, set_other_id, void, + private_ike_sa_t *this, identification_t *other) { DESTROY_IF(this->other_id); this->other_id = other; } -/** - * Implementation of ike_sa_t.add_child_sa. - */ -static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa) +METHOD(ike_sa_t, add_child_sa, void, + private_ike_sa_t *this, child_sa_t *child_sa) { this->child_sas->insert_last(this->child_sas, child_sa); } -/** - * Implementation of ike_sa_t.get_child_sa. - */ -static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol, - u_int32_t spi, bool inbound) +METHOD(ike_sa_t, get_child_sa, child_sa_t*, + private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool inbound) { iterator_t *iterator; child_sa_t *current, *found = NULL; @@ -1479,19 +1362,14 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol, return found; } -/** - * Implementation of ike_sa_t.create_child_sa_iterator. - */ -static iterator_t* create_child_sa_iterator(private_ike_sa_t *this) +METHOD(ike_sa_t, create_child_sa_iterator, iterator_t*, + private_ike_sa_t *this) { return this->child_sas->create_iterator(this->child_sas, TRUE); } -/** - * Implementation of ike_sa_t.rekey_child_sa. - */ -static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol, - u_int32_t spi) +METHOD(ike_sa_t, rekey_child_sa, status_t, + private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) { child_rekey_t *child_rekey; @@ -1500,11 +1378,8 @@ static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.delete_child_sa. - */ -static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol, - u_int32_t spi) +METHOD(ike_sa_t, delete_child_sa, status_t, + private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) { child_delete_t *child_delete; @@ -1513,11 +1388,8 @@ static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol, return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.destroy_child_sa. - */ -static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol, - u_int32_t spi) +METHOD(ike_sa_t, destroy_child_sa, status_t, + private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi) { iterator_t *iterator; child_sa_t *child_sa; @@ -1539,10 +1411,8 @@ static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol, return status; } -/** - * Implementation of public_ike_sa_t.delete. - */ -static status_t delete_(private_ike_sa_t *this) +METHOD(ike_sa_t, delete_, status_t, + private_ike_sa_t *this) { ike_delete_t *ike_delete; @@ -1567,10 +1437,8 @@ static status_t delete_(private_ike_sa_t *this) return DESTROY_ME; } -/** - * Implementation of ike_sa_t.rekey. - */ -static status_t rekey(private_ike_sa_t *this) +METHOD(ike_sa_t, rekey, status_t, + private_ike_sa_t *this) { ike_rekey_t *ike_rekey; @@ -1580,10 +1448,8 @@ static status_t rekey(private_ike_sa_t *this) return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.reauth - */ -static status_t reauth(private_ike_sa_t *this) +METHOD(ike_sa_t, reauth, status_t, + private_ike_sa_t *this) { task_t *task; @@ -1618,10 +1484,8 @@ static status_t reauth(private_ike_sa_t *this) return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.reestablish - */ -static status_t reestablish(private_ike_sa_t *this) +METHOD(ike_sa_t, reestablish, status_t, + private_ike_sa_t *this) { ike_sa_t *new; host_t *host; @@ -1636,14 +1500,13 @@ static status_t reestablish(private_ike_sa_t *this) iterator = create_child_sa_iterator(this); while (iterator->iterate(iterator, (void**)&child_sa)) { - child_cfg = child_sa->get_config(child_sa); if (this->state == IKE_DELETING) { - action = child_cfg->get_close_action(child_cfg); + action = child_sa->get_close_action(child_sa); } else { - action = child_cfg->get_dpd_action(child_cfg); + action = child_sa->get_dpd_action(child_sa); } switch (action) { @@ -1651,7 +1514,8 @@ static status_t reestablish(private_ike_sa_t *this) restart = TRUE; break; case ACTION_ROUTE: - charon->traps->install(charon->traps, this->peer_cfg, child_cfg); + charon->traps->install(charon->traps, this->peer_cfg, + child_sa->get_config(child_sa)); break; default: break; @@ -1707,18 +1571,18 @@ static status_t reestablish(private_ike_sa_t *this) iterator = create_child_sa_iterator(this); while (iterator->iterate(iterator, (void**)&child_sa)) { - child_cfg = child_sa->get_config(child_sa); if (this->state == IKE_DELETING) { - action = child_cfg->get_close_action(child_cfg); + action = child_sa->get_close_action(child_sa); } else { - action = child_cfg->get_dpd_action(child_cfg); + action = child_sa->get_dpd_action(child_sa); } switch (action) { case ACTION_RESTART: + child_cfg = child_sa->get_config(child_sa); DBG1(DBG_IKE, "restarting CHILD_SA %s", child_cfg->get_name(child_cfg)); child_cfg->get_ref(child_cfg); @@ -1750,9 +1614,41 @@ static status_t reestablish(private_ike_sa_t *this) } /** - * Implementation of ike_sa_t.retransmit. + * Requeue the IKE_SA_INIT tasks for initiation, if required */ -static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) +static void requeue_init_tasks(private_ike_sa_t *this) +{ + enumerator_t *enumerator; + bool has_init = FALSE; + task_t *task; + + /* if we have advanced to IKE_AUTH, the IKE_INIT and related tasks + * have already completed. Recreate them if necessary. */ + enumerator = this->task_manager->create_task_enumerator( + this->task_manager, TASK_QUEUE_QUEUED); + while (enumerator->enumerate(enumerator, &task)) + { + if (task->get_type(task) == IKE_INIT) + { + has_init = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + if (!has_init) + { + task = (task_t*)ike_vendor_create(&this->public, TRUE); + this->task_manager->queue_task(this->task_manager, task); + task = (task_t*)ike_natd_create(&this->public, TRUE); + this->task_manager->queue_task(this->task_manager, task); + task = (task_t*)ike_init_create(&this->public, TRUE, NULL); + this->task_manager->queue_task(this->task_manager, task); + } +} + +METHOD(ike_sa_t, retransmit, status_t, + private_ike_sa_t *this, u_int32_t message_id) { this->stats[STAT_OUTBOUND] = time_monotonic(NULL); if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) @@ -1770,6 +1666,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)", this->keyingtry + 1, tries); reset(this); + requeue_init_tasks(this); return this->task_manager->initiate(this->task_manager); } DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding"); @@ -1790,10 +1687,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) return SUCCESS; } -/** - * Implementation of ike_sa_t.set_auth_lifetime. - */ -static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime) +METHOD(ike_sa_t, set_auth_lifetime, void, + private_ike_sa_t *this, u_int32_t lifetime) { u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg); u_int32_t reauth_time = time_monotonic(NULL) + lifetime - reduction; @@ -1823,10 +1718,8 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime) } } -/** - * Implementation of ike_sa_t.roam. - */ -static status_t roam(private_ike_sa_t *this, bool address) +METHOD(ike_sa_t, roam, status_t, + private_ike_sa_t *this, bool address) { host_t *src; ike_mobike_t *mobike; @@ -1919,12 +1812,9 @@ static status_t roam(private_ike_sa_t *this, bool address) return reauth(this); } -/** - * Implementation of ike_sa_t.add_configuration_attribute - */ -static void add_configuration_attribute(private_ike_sa_t *this, - attribute_handler_t *handler, - configuration_attribute_type_t type, chunk_t data) +METHOD(ike_sa_t, add_configuration_attribute, void, + private_ike_sa_t *this, attribute_handler_t *handler, + configuration_attribute_type_t type, chunk_t data) { attribute_entry_t *entry = malloc_thing(attribute_entry_t); @@ -1935,11 +1825,16 @@ static void add_configuration_attribute(private_ike_sa_t *this, this->attributes->insert_last(this->attributes, entry); } -/** - * Implementation of ike_sa_t.inherit. - */ -static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) +METHOD(ike_sa_t, create_task_enumerator, enumerator_t*, + private_ike_sa_t *this, task_queue_t queue) +{ + return this->task_manager->create_task_enumerator(this->task_manager, queue); +} + +METHOD(ike_sa_t, inherit, status_t, + private_ike_sa_t *this, ike_sa_t *other_public) { + private_ike_sa_t *other = (private_ike_sa_t*)other_public; child_sa_t *child_sa; attribute_entry_t *entry; @@ -2021,10 +1916,8 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other) return this->task_manager->initiate(this->task_manager); } -/** - * Implementation of ike_sa_t.destroy. - */ -static void destroy(private_ike_sa_t *this) +METHOD(ike_sa_t, destroy, void, + private_ike_sa_t *this) { attribute_entry_t *entry; @@ -2106,122 +1999,107 @@ static void destroy(private_ike_sa_t *this) */ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) { - private_ike_sa_t *this = malloc_thing(private_ike_sa_t); + private_ike_sa_t *this; static u_int32_t unique_id = 0; - /* Public functions */ - this->public.get_state = (ike_sa_state_t (*)(ike_sa_t*)) get_state; - this->public.set_state = (void (*)(ike_sa_t*,ike_sa_state_t)) set_state; - this->public.get_name = (char* (*)(ike_sa_t*))get_name; - this->public.get_statistic = (u_int32_t(*)(ike_sa_t*, statistic_t kind))get_statistic; - this->public.process_message = (status_t (*)(ike_sa_t*, message_t*)) process_message; - this->public.initiate = (status_t (*)(ike_sa_t*,child_cfg_t*,u_int32_t,traffic_selector_t*,traffic_selector_t*)) initiate; - this->public.get_ike_cfg = (ike_cfg_t* (*)(ike_sa_t*))get_ike_cfg; - this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg; - this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg; - this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg; - this->public.get_auth_cfg = (auth_cfg_t*(*)(ike_sa_t*, bool local))get_auth_cfg; - this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(ike_sa_t*, bool local))create_auth_cfg_enumerator; - this->public.add_auth_cfg = (void(*)(ike_sa_t*, bool local, auth_cfg_t *cfg))add_auth_cfg; - this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal; - this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal; - this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id; - this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host; - this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host; - this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host; - this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_other_host; - this->public.set_message_id = (void(*)(ike_sa_t*, bool inbound, u_int32_t mid))set_message_id; - this->public.update_hosts = (void(*)(ike_sa_t*, host_t *me, host_t *other))update_hosts; - this->public.get_my_id = (identification_t* (*)(ike_sa_t*)) get_my_id; - this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id; - this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id; - this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id; - this->public.get_other_eap_id = (identification_t* (*)(ike_sa_t*)) get_other_eap_id; - this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension; - this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension; - this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition; - this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition; - this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates; - this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates; - this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator; - this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address; - this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed; - this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit; - this->public.delete = (status_t (*)(ike_sa_t*))delete_; - this->public.destroy = (void (*)(ike_sa_t*))destroy; - this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd; - this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive; - this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat; - this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa; - this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa; - this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator; - this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa; - this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa; - this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa; - this->public.rekey = (status_t (*)(ike_sa_t*))rekey; - this->public.reauth = (status_t (*)(ike_sa_t*))reauth; - this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish; - this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime; - this->public.roam = (status_t(*)(ike_sa_t*,bool))roam; - this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit; - this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message; - this->public.reset = (void (*)(ike_sa_t*))reset; - this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id; - this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip; - this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip; - this->public.add_configuration_attribute = (void(*)(ike_sa_t*, attribute_handler_t *handler,configuration_attribute_type_t type, chunk_t data))add_configuration_attribute; - this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress; + INIT(this, + .public = { + .get_state = _get_state, + .set_state = _set_state, + .get_name = _get_name, + .get_statistic = _get_statistic, + .process_message = _process_message, + .initiate = _initiate, + .get_ike_cfg = _get_ike_cfg, + .set_ike_cfg = _set_ike_cfg, + .get_peer_cfg = _get_peer_cfg, + .set_peer_cfg = _set_peer_cfg, + .get_auth_cfg = _get_auth_cfg, + .create_auth_cfg_enumerator = _create_auth_cfg_enumerator, + .add_auth_cfg = _add_auth_cfg, + .get_proposal = _get_proposal, + .set_proposal = _set_proposal, + .get_id = _get_id, + .get_my_host = _get_my_host, + .set_my_host = _set_my_host, + .get_other_host = _get_other_host, + .set_other_host = _set_other_host, + .set_message_id = _set_message_id, + .update_hosts = _update_hosts, + .get_my_id = _get_my_id, + .set_my_id = _set_my_id, + .get_other_id = _get_other_id, + .set_other_id = _set_other_id, + .get_other_eap_id = _get_other_eap_id, + .enable_extension = _enable_extension, + .supports_extension = _supports_extension, + .set_condition = _set_condition, + .has_condition = _has_condition, + .set_pending_updates = _set_pending_updates, + .get_pending_updates = _get_pending_updates, + .create_additional_address_iterator = _create_additional_address_iterator, + .add_additional_address = _add_additional_address, + .has_mapping_changed = _has_mapping_changed, + .retransmit = _retransmit, + .delete = _delete_, + .destroy = _destroy, + .send_dpd = _send_dpd, + .send_keepalive = _send_keepalive, + .get_keymat = _get_keymat, + .add_child_sa = _add_child_sa, + .get_child_sa = _get_child_sa, + .create_child_sa_iterator = _create_child_sa_iterator, + .rekey_child_sa = _rekey_child_sa, + .delete_child_sa = _delete_child_sa, + .destroy_child_sa = _destroy_child_sa, + .rekey = _rekey, + .reauth = _reauth, + .reestablish = _reestablish, + .set_auth_lifetime = _set_auth_lifetime, + .roam = _roam, + .inherit = _inherit, + .generate_message = _generate_message, + .reset = _reset, + .get_unique_id = _get_unique_id, + .set_virtual_ip = _set_virtual_ip, + .get_virtual_ip = _get_virtual_ip, + .add_configuration_attribute = _add_configuration_attribute, + .set_kmaddress = _set_kmaddress, + .create_task_enumerator = _create_task_enumerator, #ifdef ME - this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server; - this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host; - this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host; - this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id; - this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation; - this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,chunk_t)) initiate_mediated; - this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay; - this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback; - this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond; + .act_as_mediation_server = _act_as_mediation_server, + .get_server_reflexive_host = _get_server_reflexive_host, + .set_server_reflexive_host = _set_server_reflexive_host, + .get_connect_id = _get_connect_id, + .initiate_mediation = _initiate_mediation, + .initiate_mediated = _initiate_mediated, + .relay = _relay, + .callback = _callback, + .respond = _respond, #endif /* ME */ - - /* initialize private fields */ - this->ike_sa_id = ike_sa_id->clone(ike_sa_id); - this->child_sas = linked_list_create(); - this->my_host = host_create_any(AF_INET); + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + .child_sas = linked_list_create(), + .my_host = host_create_any(AF_INET), + .other_host = host_create_any(AF_INET), + .my_id = identification_create_from_encoding(ID_ANY, chunk_empty), + .other_id = identification_create_from_encoding(ID_ANY, chunk_empty), + .keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id)), + .state = IKE_CREATED, + .stats[STAT_INBOUND] = time_monotonic(NULL), + .stats[STAT_OUTBOUND] = time_monotonic(NULL), + .my_auth = auth_cfg_create(), + .other_auth = auth_cfg_create(), + .my_auths = linked_list_create(), + .other_auths = linked_list_create(), + .task_manager = task_manager_create(&this->public), + .unique_id = ++unique_id, + .additional_addresses = linked_list_create(), + .attributes = linked_list_create(), + .keepalive_interval = lib->settings->get_time(lib->settings, + "charon.keep_alive", KEEPALIVE_INTERVAL), + ); this->my_host->set_port(this->my_host, IKEV2_UDP_PORT); - this->other_host = host_create_any(AF_INET); - this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty); - this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty); - this->extensions = 0; - this->conditions = 0; - this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id)); - this->state = IKE_CREATED; - this->keepalive_interval = lib->settings->get_time(lib->settings, - "charon.keep_alive", KEEPALIVE_INTERVAL); - memset(this->stats, 0, sizeof(this->stats)); - this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time_monotonic(NULL); - this->ike_cfg = NULL; - this->peer_cfg = NULL; - this->my_auth = auth_cfg_create(); - this->other_auth = auth_cfg_create(); - this->my_auths = linked_list_create(); - this->other_auths = linked_list_create(); - this->proposal = NULL; - this->task_manager = task_manager_create(&this->public); - this->unique_id = ++unique_id; - this->my_virtual_ip = NULL; - this->other_virtual_ip = NULL; - this->additional_addresses = linked_list_create(); - this->attributes = linked_list_create(); - this->nat_detection_dest = chunk_empty; - this->pending_updates = 0; - this->keyingtry = 0; - this->local_host = NULL; - this->remote_host = NULL; -#ifdef ME - this->is_mediation_server = FALSE; - this->server_reflexive_host = NULL; - this->connect_id = chunk_empty; -#endif /* ME */ return &this->public; } diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index c61502edf..34842a573 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -37,11 +37,11 @@ typedef struct ike_sa_t ike_sa_t; #include <encoding/payloads/configuration_attribute.h> #include <sa/ike_sa_id.h> #include <sa/child_sa.h> -#include <sa/tasks/task.h> +#include <sa/task_manager.h> #include <sa/keymat.h> #include <config/peer_cfg.h> #include <config/ike_cfg.h> -#include <config/auth_cfg.h> +#include <credentials/auth_cfg.h> /** * Timeout in seconds after that a half open IKE_SA gets deleted. @@ -888,6 +888,14 @@ struct ike_sa_t { void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote); /** + * Create enumerator over a task queue of this IKE_SA. + * + * @param queue type to enumerate + * @return enumerator over task_t + */ + enumerator_t* (*create_task_enumerator)(ike_sa_t *this, task_queue_t queue); + + /** * Inherit all attributes of other to this after rekeying. * * When rekeying is completed, all CHILD_SAs, the virtual IP and all diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 3ef0f3bb0..c71c3b297 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -886,9 +886,10 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id { if (wait_for_entry(this, entry, segment)) { - DBG2(DBG_MGR, "IKE_SA successfully checked out"); entry->checked_out = TRUE; ike_sa = entry->ike_sa; + DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); } unlock_single_segment(this, segment); } @@ -916,7 +917,8 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator) } ike_sa = ike_sa_create(ike_sa_id); - DBG2(DBG_MGR, "created IKE_SA"); + DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa)); if (!initiator) { @@ -971,10 +973,11 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, } else if (wait_for_entry(this, entry, segment)) { - DBG2(DBG_MGR, "IKE_SA checked out by hash"); entry->checked_out = TRUE; entry->message_id = message->get_message_id(message); ike_sa = entry->ike_sa; + DBG2(DBG_MGR, "IKE_SA %s[%u] checked out by hash", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); } unlock_single_segment(this, segment); } @@ -998,7 +1001,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, entry->init_hash = hash; ike_sa = entry->ike_sa; - DBG2(DBG_MGR, "created IKE_SA"); + DBG2(DBG_MGR, "created IKE_SA %s[%u]", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); } else { @@ -1027,7 +1031,6 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, else if (wait_for_entry(this, entry, segment)) { ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa); - DBG2(DBG_MGR, "IKE_SA successfully checked out"); entry->checked_out = TRUE; entry->message_id = message->get_message_id(message); if (ike_id->get_responder_spi(ike_id) == 0) @@ -1035,6 +1038,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this, ike_id->set_responder_spi(ike_id, id->get_responder_spi(id)); } ike_sa = entry->ike_sa; + DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); } unlock_single_segment(this, segment); } @@ -1056,6 +1061,8 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, ike_cfg_t *current_ike; u_int segment; + DBG2(DBG_MGR, "checkout IKE_SA by config"); + if (!this->reuse_ikesa) { /* IKE_SA reuse disable by config */ ike_sa = checkout_new(this, TRUE); @@ -1081,10 +1088,11 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this, current_ike = current_peer->get_ike_cfg(current_peer); if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg))) { - DBG2(DBG_MGR, "found an existing IKE_SA with a '%s' config", - current_peer->get_name(current_peer)); entry->checked_out = TRUE; ike_sa = entry->ike_sa; + DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config", + ike_sa->get_unique_id(ike_sa), + current_peer->get_name(current_peer)); break; } } @@ -1112,6 +1120,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, child_sa_t *child_sa; u_int segment; + DBG2(DBG_MGR, "checkout IKE_SA by ID"); + enumerator = create_table_enumerator(this); while (enumerator->enumerate(enumerator, &entry, &segment)) { @@ -1142,6 +1152,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id, if (ike_sa) { entry->checked_out = TRUE; + DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); break; } } @@ -1195,6 +1207,8 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name, if (ike_sa) { entry->checked_out = TRUE; + DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa)); break; } } @@ -1251,7 +1265,8 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) other_id = ike_sa->get_other_id(ike_sa); other = ike_sa->get_other_host(ike_sa); - DBG2(DBG_MGR, "checkin IKE_SA"); + DBG2(DBG_MGR, "checkin IKE_SA %s[%u]", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa)); /* look for the entry */ if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS) @@ -1327,7 +1342,8 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa ike_sa_id = ike_sa->get_id(ike_sa); - DBG2(DBG_MGR, "checkin and destroy IKE_SA"); + DBG2(DBG_MGR, "checkin and destroy IKE_SA %s[%u]", ike_sa->get_name(ike_sa), + ike_sa->get_unique_id(ike_sa)); if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS) { diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c index eeda6c860..a68826440 100644 --- a/src/libcharon/sa/task_manager.c +++ b/src/libcharon/sa/task_manager.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Tobias Brunner - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2007-2010 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -195,10 +195,8 @@ static bool activate_task(private_task_manager_t *this, task_type_t type) return found; } -/** - * Implementation of task_manager_t.retransmit - */ -static status_t retransmit(private_task_manager_t *this, u_int32_t message_id) +METHOD(task_manager_t, retransmit, status_t, + private_task_manager_t *this, u_int32_t message_id) { if (message_id == this->initiating.mid) { @@ -281,11 +279,8 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id) return SUCCESS; } -/** - * build a request using the active task list - * Implementation of task_manager_t.initiate - */ -static status_t build_request(private_task_manager_t *this) +METHOD(task_manager_t, initiate, status_t, + private_task_manager_t *this) { iterator_t *iterator; task_t *task; @@ -296,7 +291,8 @@ static status_t build_request(private_task_manager_t *this) if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED) { - DBG2(DBG_IKE, "delaying task initiation, exchange in progress"); + DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress", + exchange_type_names, this->initiating.type); /* do not initiate if we already have a message in the air */ return SUCCESS; } @@ -534,7 +530,7 @@ static status_t process_response(private_task_manager_t *this, { /* start all over again if we were reset */ this->reset = FALSE; iterator->destroy(iterator); - return build_request(this); + return initiate(this); } } iterator->destroy(iterator); @@ -544,7 +540,7 @@ static status_t process_response(private_task_manager_t *this, this->initiating.packet->destroy(this->initiating.packet); this->initiating.packet = NULL; - return build_request(this); + return initiate(this); } /** @@ -883,10 +879,8 @@ static status_t process_request(private_task_manager_t *this, return build_response(this, message); } -/** - * Implementation of task_manager_t.process_message - */ -static status_t process_message(private_task_manager_t *this, message_t *msg) +METHOD(task_manager_t, process_message, status_t, + private_task_manager_t *this, message_t *msg) { u_int32_t mid = msg->get_message_id(msg); @@ -943,10 +937,8 @@ static status_t process_message(private_task_manager_t *this, message_t *msg) return SUCCESS; } -/** - * Implementation of task_manager_t.queue_task - */ -static void queue_task(private_task_manager_t *this, task_t *task) +METHOD(task_manager_t, queue_task, void, + private_task_manager_t *this, task_t *task) { if (task->get_type(task) == IKE_MOBIKE) { /* there is no need to queue more than one mobike task */ @@ -969,11 +961,10 @@ static void queue_task(private_task_manager_t *this, task_t *task) this->queued_tasks->insert_last(this->queued_tasks, task); } -/** - * Implementation of task_manager_t.adopt_tasks - */ -static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other) +METHOD(task_manager_t, adopt_tasks, void, + private_task_manager_t *this, task_manager_t *other_public) { + private_task_manager_t *other = (private_task_manager_t*)other_public; task_t *task; /* move queued tasks from other to this */ @@ -986,20 +977,16 @@ static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *ot } } -/** - * Implementation of task_manager_t.busy - */ -static bool busy(private_task_manager_t *this) +METHOD(task_manager_t, busy, bool, + private_task_manager_t *this) { return (this->active_tasks->get_count(this->active_tasks) > 0); } -/** - * Implementation of task_manager_t.reset - */ -static void reset(private_task_manager_t *this, - u_int32_t initiate, u_int32_t respond) +METHOD(task_manager_t, reset, void, + private_task_manager_t *this, u_int32_t initiate, u_int32_t respond) { + enumerator_t *enumerator; task_t *task; /* reset message counters and retransmit packets */ @@ -1017,6 +1004,14 @@ static void reset(private_task_manager_t *this, } this->initiating.type = EXCHANGE_TYPE_UNDEFINED; + /* reset queued tasks */ + enumerator = this->queued_tasks->create_enumerator(this->queued_tasks); + while (enumerator->enumerate(enumerator, &task)) + { + task->migrate(task, this->ike_sa); + } + enumerator->destroy(enumerator); + /* reset active tasks */ while (this->active_tasks->remove_last(this->active_tasks, (void**)&task) == SUCCESS) @@ -1028,10 +1023,24 @@ static void reset(private_task_manager_t *this, this->reset = TRUE; } -/** - * Implementation of task_manager_t.destroy - */ -static void destroy(private_task_manager_t *this) +METHOD(task_manager_t, create_task_enumerator, enumerator_t*, + private_task_manager_t *this, task_queue_t queue) +{ + switch (queue) + { + case TASK_QUEUE_ACTIVE: + return this->active_tasks->create_enumerator(this->active_tasks); + case TASK_QUEUE_PASSIVE: + return this->passive_tasks->create_enumerator(this->passive_tasks); + case TASK_QUEUE_QUEUED: + return this->queued_tasks->create_enumerator(this->queued_tasks); + default: + return enumerator_create_empty(); + } +} + +METHOD(task_manager_t, destroy, void, + private_task_manager_t *this) { flush(this); @@ -1049,34 +1058,32 @@ static void destroy(private_task_manager_t *this) */ task_manager_t *task_manager_create(ike_sa_t *ike_sa) { - private_task_manager_t *this = malloc_thing(private_task_manager_t); - - this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message; - this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task; - this->public.initiate = (status_t(*)(task_manager_t*))build_request; - this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit; - this->public.reset = (void(*)(task_manager_t*,u_int32_t,u_int32_t))reset; - this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks; - this->public.busy = (bool(*)(task_manager_t*))busy; - this->public.destroy = (void(*)(task_manager_t*))destroy; - - this->ike_sa = ike_sa; - this->responding.packet = NULL; - this->initiating.packet = NULL; - this->responding.mid = 0; - this->initiating.mid = 0; - this->initiating.type = EXCHANGE_TYPE_UNDEFINED; - this->queued_tasks = linked_list_create(); - this->active_tasks = linked_list_create(); - this->passive_tasks = linked_list_create(); - this->reset = FALSE; - - this->retransmit_tries = lib->settings->get_int(lib->settings, - "charon.retransmit_tries", RETRANSMIT_TRIES); - this->retransmit_timeout = lib->settings->get_double(lib->settings, - "charon.retransmit_timeout", RETRANSMIT_TIMEOUT); - this->retransmit_base = lib->settings->get_double(lib->settings, - "charon.retransmit_base", RETRANSMIT_BASE); + private_task_manager_t *this; + + INIT(this, + .public = { + .process_message = _process_message, + .queue_task = _queue_task, + .initiate = _initiate, + .retransmit = _retransmit, + .reset = _reset, + .adopt_tasks = _adopt_tasks, + .busy = _busy, + .create_task_enumerator = _create_task_enumerator, + .destroy = _destroy, + }, + .ike_sa = ike_sa, + .initiating.type = EXCHANGE_TYPE_UNDEFINED, + .queued_tasks = linked_list_create(), + .active_tasks = linked_list_create(), + .passive_tasks = linked_list_create(), + .retransmit_tries = lib->settings->get_int(lib->settings, + "charon.retransmit_tries", RETRANSMIT_TRIES), + .retransmit_timeout = lib->settings->get_double(lib->settings, + "charon.retransmit_timeout", RETRANSMIT_TIMEOUT), + .retransmit_base = lib->settings->get_double(lib->settings, + "charon.retransmit_base", RETRANSMIT_BASE), + ); return &this->public; } diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h index 731ed4898..14fccd5f9 100644 --- a/src/libcharon/sa/task_manager.h +++ b/src/libcharon/sa/task_manager.h @@ -22,6 +22,7 @@ #define TASK_MANAGER_H_ typedef struct task_manager_t task_manager_t; +typedef enum task_queue_t task_queue_t; #include <limits.h> @@ -55,6 +56,17 @@ typedef struct task_manager_t task_manager_t; */ #define ROUTEABILITY_CHECK_TRIES 10 +/** + * Type of task queues the task manager uses to handle tasks + */ +enum task_queue_t { + /** tasks currently active, initiated by us */ + TASK_QUEUE_ACTIVE, + /** passive tasks initiated by the remote peer */ + TASK_QUEUE_PASSIVE, + /** tasks queued for initiated, but not yet activated */ + TASK_QUEUE_QUEUED, +}; /** * The task manager, juggles task and handles message exchanges. @@ -158,6 +170,15 @@ struct task_manager_t { bool (*busy) (task_manager_t *this); /** + * Create an enumerator over tasks in a specific queue. + * + * @param queue queue to create an enumerator over + * @return enumerator over task_t + */ + enumerator_t* (*create_task_enumerator)(task_manager_t *this, + task_queue_t queue); + + /** * Destroy the task_manager_t. */ void (*destroy) (task_manager_t *this); diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c index bea4f73d5..3de27ee3f 100644 --- a/src/libcharon/sa/tasks/child_create.c +++ b/src/libcharon/sa/tasks/child_create.c @@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this) * - INVALID_ARG: diffie hellman group inacceptable * - NOT_FOUND: TS inacceptable */ -static status_t select_and_install(private_child_create_t *this, bool no_dh) +static status_t select_and_install(private_child_create_t *this, + bool no_dh, bool ike_auth) { status_t status, status_i, status_o; chunk_t nonce_i, nonce_r; @@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts, other_vip); + if (this->initiator) + { + if (ike_auth) + { + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts); + } + else + { + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_INITIATOR_POST_AUTH, my_ts, other_ts); + } + } + else + { + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_RESPONDER, my_ts, other_ts); + } + if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0) { my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); @@ -418,66 +438,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) } } - /* check for any certificate-based IP address block constraints */ - if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL) - { - auth_cfg_t *auth; - enumerator_t *auth_enum; - certificate_t *cert = NULL; - - auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE); - while (auth_enum->enumerate(auth_enum, &auth)) - { - cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT); - if (cert) - { - break; - } - } - auth_enum->destroy(auth_enum); - - if (cert && cert->get_type(cert) == CERT_X509) - { - x509_t *x509 = (x509_t*)cert; - - if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS) - { - enumerator_t *enumerator, *block_enum; - traffic_selector_t *ts, *block_ts; - - DBG1(DBG_IKE, "checking certificate-based traffic selector " - "constraints [RFC 3779]"); - enumerator = other_ts->create_enumerator(other_ts); - while (enumerator->enumerate(enumerator, &ts)) - { - bool contained = FALSE; - - block_enum = x509->create_ipAddrBlock_enumerator(x509); - while (block_enum->enumerate(block_enum, &block_ts)) - { - if (ts->is_contained_in(ts, block_ts)) - { - DBG1(DBG_IKE, " TS %R is contained in address block" - " constraint %R", ts, block_ts); - contained = TRUE; - break; - } - } - block_enum->destroy(block_enum); - - if (!contained) - { - DBG1(DBG_IKE, " TS %R is not contained in any" - " address block constraint", ts); - enumerator->destroy(enumerator); - return FAILED; - } - } - enumerator->destroy(enumerator); - } - } - } - this->child_sa->set_state(this->child_sa, CHILD_INSTALLING); this->child_sa->set_ipcomp(this->child_sa, this->ipcomp); this->child_sa->set_mode(this->child_sa, this->mode); @@ -529,8 +489,8 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) return NOT_FOUND; } - charon->bus->child_keys(charon->bus, this->child_sa, this->dh, - nonce_i, nonce_r); + charon->bus->child_keys(charon->bus, this->child_sa, this->initiator, + this->dh, nonce_i, nonce_r); /* add to IKE_SA, and remove from task */ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); @@ -848,6 +808,17 @@ static status_t build_i(private_child_create_t *this, message_t *message) add_ipcomp_notify(this, message, IPCOMP_DEFLATE); } + if (message->get_exchange_type(message) == IKE_AUTH) + { + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr); + } + else + { + charon->bus->narrow(charon->bus, this->child_sa, + NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr); + } + build_payloads(this, message); this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); @@ -914,7 +885,7 @@ static status_t build_r(private_child_create_t *this, message_t *message) peer_cfg_t *peer_cfg; payload_t *payload; enumerator_t *enumerator; - bool no_dh = TRUE; + bool no_dh = TRUE, ike_auth = FALSE; switch (message->get_exchange_type(message)) { @@ -934,6 +905,7 @@ static status_t build_r(private_child_create_t *this, message_t *message) { /* wait until all authentication round completed */ return NEED_MORE; } + ike_auth = TRUE; default: break; } @@ -1016,7 +988,7 @@ static status_t build_r(private_child_create_t *this, message_t *message) } } - switch (select_and_install(this, no_dh)) + switch (select_and_install(this, no_dh, ike_auth)) { case SUCCESS: break; @@ -1064,7 +1036,7 @@ static status_t process_i(private_child_create_t *this, message_t *message) { enumerator_t *enumerator; payload_t *payload; - bool no_dh = TRUE; + bool no_dh = TRUE, ike_auth = FALSE; switch (message->get_exchange_type(message)) { @@ -1079,6 +1051,7 @@ static status_t process_i(private_child_create_t *this, message_t *message) { /* wait until all authentication round completed */ return NEED_MORE; } + ike_auth = TRUE; default: break; } @@ -1159,7 +1132,7 @@ static status_t process_i(private_child_create_t *this, message_t *message) return SUCCESS; } - if (select_and_install(this, no_dh) == SUCCESS) + if (select_and_install(this, no_dh, ike_auth) == SUCCESS) { DBG0(DBG_IKE, "CHILD_SA %s{%d} established " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", @@ -1229,11 +1202,11 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) { chunk_free(&this->my_nonce); chunk_free(&this->other_nonce); - if (this->tsi) + if (this->tsr) { this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); } - if (this->tsr) + if (this->tsi) { this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); } diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c index d7c6b0541..b0cd30e1e 100644 --- a/src/libcharon/sa/tasks/child_delete.c +++ b/src/libcharon/sa/tasks/child_delete.c @@ -191,6 +191,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this) child_cfg_t *child_cfg; protocol_id_t protocol; u_int32_t spi; + action_t action; status_t status = SUCCESS; iterator = this->child_sas->create_iterator(this->child_sas, TRUE); @@ -205,10 +206,11 @@ static status_t destroy_and_reestablish(private_child_delete_t *this) protocol = child_sa->get_protocol(child_sa); child_cfg = child_sa->get_config(child_sa); child_cfg->get_ref(child_cfg); + action = child_sa->get_close_action(child_sa); this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi); if (this->check_delete_action) { /* enforce child_cfg policy if deleted passively */ - switch (child_cfg->get_close_action(child_cfg)) + switch (action) { case ACTION_RESTART: child_cfg->get_ref(child_cfg); diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c index b5e4e84b4..fb3452efd 100644 --- a/src/libcharon/sa/tasks/child_rekey.c +++ b/src/libcharon/sa/tasks/child_rekey.c @@ -215,6 +215,64 @@ static status_t build_r(private_child_rekey_t *this, message_t *message) } /** + * Handle a rekey collision + */ +static child_sa_t *handle_collision(private_child_rekey_t *this) +{ + child_sa_t *to_delete; + + if (this->collision->get_type(this->collision) == CHILD_REKEY) + { + chunk_t this_nonce, other_nonce; + private_child_rekey_t *other = (private_child_rekey_t*)this->collision; + + this_nonce = this->child_create->get_lower_nonce(this->child_create); + other_nonce = other->child_create->get_lower_nonce(other->child_create); + + /* if we have the lower nonce, delete rekeyed SA. If not, delete + * the redundant. */ + if (memcmp(this_nonce.ptr, other_nonce.ptr, + min(this_nonce.len, other_nonce.len)) < 0) + { + child_sa_t *child_sa; + + DBG1(DBG_IKE, "CHILD_SA rekey collision won, " + "deleting rekeyed child"); + to_delete = this->child_sa; + /* disable close action for the redundand child */ + child_sa = other->child_create->get_child(other->child_create); + child_sa->set_close_action(child_sa, ACTION_NONE); + } + else + { + DBG1(DBG_IKE, "CHILD_SA rekey collision lost, " + "deleting redundant child"); + to_delete = this->child_create->get_child(this->child_create); + } + } + else + { /* CHILD_DELETE */ + child_delete_t *del = (child_delete_t*)this->collision; + + /* we didn't had a chance to compare the nonces, so we delete + * the CHILD_SA the other is not deleting. */ + if (del->get_child(del) != this->child_sa) + { + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " + "deleting rekeyed child"); + to_delete = this->child_sa; + } + else + { + DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, " + "deleting redundant child"); + to_delete = this->child_create->get_child(this->child_create); + } + } + return to_delete; +} + +/** * Implementation of task_t.process for initiator */ static status_t process_i(private_child_rekey_t *this, message_t *message) @@ -263,35 +321,14 @@ static status_t process_i(private_child_rekey_t *this, message_t *message) return SUCCESS; } - to_delete = this->child_sa; - /* check for rekey collisions */ - if (this->collision && - this->collision->get_type(this->collision) == CHILD_REKEY) + if (this->collision) { - chunk_t this_nonce, other_nonce; - private_child_rekey_t *other = (private_child_rekey_t*)this->collision; - - this_nonce = this->child_create->get_lower_nonce(this->child_create); - other_nonce = other->child_create->get_lower_nonce(other->child_create); - - /* if we have the lower nonce, delete rekeyed SA. If not, delete - * the redundant. */ - if (memcmp(this_nonce.ptr, other_nonce.ptr, - min(this_nonce.len, other_nonce.len)) < 0) - { - DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child"); - } - else - { - DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child"); - to_delete = this->child_create->get_child(this->child_create); - if (to_delete == NULL) - { - /* ooops, should not happen, fallback */ - to_delete = this->child_sa; - } - } + to_delete = handle_collision(this); + } + else + { + to_delete = this->child_sa; } if (to_delete != this->child_create->get_child(this->child_create)) @@ -300,6 +337,10 @@ static status_t process_i(private_child_rekey_t *this, message_t *message) this->child_create->get_child(this->child_create)); } + if (to_delete == NULL) + { + return SUCCESS; + } spi = to_delete->get_spi(to_delete, TRUE); protocol = to_delete->get_protocol(to_delete); diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c index a07f96767..a954782f2 100644 --- a/src/libcharon/sa/tasks/ike_auth.c +++ b/src/libcharon/sa/tasks/ike_auth.c @@ -518,6 +518,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) (uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK && (uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0)) { /* peer requested EAP, but current config does not match */ + DBG1(DBG_IKE, "peer requested EAP, config inacceptable"); this->peer_cfg->destroy(this->peer_cfg); this->peer_cfg = NULL; if (!update_cfg_candidates(this, FALSE)) @@ -527,7 +528,16 @@ static status_t process_r(private_ike_auth_t *this, message_t *message) } cand = get_auth_cfg(this, FALSE); } - cfg->merge(cfg, cand, TRUE); + /* copy over the EAP specific rules for authentication */ + cfg->add(cfg, AUTH_RULE_EAP_TYPE, + cand->get(cand, AUTH_RULE_EAP_TYPE)); + cfg->add(cfg, AUTH_RULE_EAP_VENDOR, + cand->get(cand, AUTH_RULE_EAP_VENDOR)); + id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY); + if (id) + { + cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id)); + } } /* verify authentication data */ diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c index c831df975..cc810a49a 100644 --- a/src/libcharon/sa/tasks/ike_cert_post.c +++ b/src/libcharon/sa/tasks/ike_cert_post.c @@ -72,14 +72,18 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, return cert_payload_create_from_cert(cert); } - encoded = cert->get_encoding(cert); + if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded)) + { + DBG1(DBG_IKE, "encoding certificate for cert payload failed"); + hasher->destroy(hasher); + return NULL; + } hasher->allocate_hash(hasher, encoded, &hash); chunk_free(&encoded); hasher->destroy(hasher); id = identification_create_from_encoding(ID_KEY_ID, hash); - enumerator = charon->credentials->create_cdp_enumerator(charon->credentials, - CERT_X509, id); + enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509, id); if (enumerator->enumerate(enumerator, &url)) { payload = cert_payload_create_from_hash_and_url(hash, url); diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c index 0805d0290..1c0c54727 100644 --- a/src/libcharon/sa/tasks/ike_cert_pre.c +++ b/src/libcharon/sa/tasks/ike_cert_pre.c @@ -93,8 +93,8 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) certificate_t *cert; id = identification_create_from_encoding(ID_KEY_ID, keyid); - cert = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, id, TRUE); + cert = lib->credmgr->get_cert(lib->credmgr, + CERT_X509, KEY_ANY, id, TRUE); if (cert) { DBG1(DBG_IKE, "received cert request for \"%Y\"", @@ -156,8 +156,8 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload) break; } id = identification_create_from_encoding(ID_KEY_ID, hash); - cert = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, id, FALSE); + cert = lib->credmgr->get_cert(lib->credmgr, + CERT_X509, KEY_ANY, id, FALSE); id->destroy(id); break; } @@ -299,7 +299,7 @@ static void add_certreq(certreq_payload_t **req, certificate_t *cert) { *req = certreq_payload_create_type(CERT_X509); } - if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid)) + if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid)) { (*req)->add_keyid(*req, keyid); DBG1(DBG_IKE, "sending cert request for \"%Y\"", @@ -370,8 +370,8 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message) if (!req) { /* otherwise add all trusted CA certificates */ - enumerator = charon->credentials->create_cert_enumerator( - charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE); + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_ANY, KEY_ANY, NULL, TRUE); while (enumerator->enumerate(enumerator, &cert)) { add_certreq(&req, cert); diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c index 58bcf0762..c92b5bca5 100644 --- a/src/libcharon/sa/tasks/ike_config.c +++ b/src/libcharon/sa/tasks/ike_config.c @@ -333,7 +333,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message) chunk_empty); return SUCCESS; } - DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip); + DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id); this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip); cp = cp_payload_create_type(CFG_REPLY); @@ -342,7 +342,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message) /* query registered providers for additional attributes to include */ enumerator = hydra->attributes->create_responder_enumerator( - hydra->attributes, id, vip); + hydra->attributes, config->get_pool(config), id, vip); while (enumerator->enumerate(enumerator, &type, &value)) { if (!cp) diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c index 5eb33b540..38fb572f4 100644 --- a/src/libcharon/sa/tasks/ike_init.c +++ b/src/libcharon/sa/tasks/ike_init.c @@ -543,6 +543,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa) chunk_free(&this->other_nonce); this->ike_sa = ike_sa; + this->keymat = ike_sa->get_keymat(ike_sa); this->proposal = NULL; DESTROY_IF(this->dh); this->dh = this->keymat->create_dh(this->keymat, this->dh_group); diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index 878170c83..80bf647cd 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -128,7 +128,7 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer, ike_cfg = peer->get_ike_cfg(peer); other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, ike_cfg->get_other_port(ike_cfg)); - if (!other) + if (!other || other->is_anyaddr(other)) { DBG1(DBG_CFG, "installing trap failed, remote address unknown"); return 0; |