diff options
Diffstat (limited to 'src/libcharon')
271 files changed, 16192 insertions, 2409 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index 4212ee87a..5eef6fdc6 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -3,6 +3,10 @@ include $(CLEAR_VARS) # copy-n-paste from Makefile.am libcharon_la_SOURCES := \ +attributes/attributes.c attributes/attributes.h \ +attributes/attribute_provider.h attributes/attribute_handler.h \ +attributes/attribute_manager.c attributes/attribute_manager.h \ +attributes/mem_pool.c attributes/mem_pool.h \ bus/bus.c bus/bus.h \ bus/listeners/listener.h \ bus/listeners/logger.h \ @@ -62,6 +66,7 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ +processing/jobs/initiate_tasks_job.c processing/jobs/initiate_tasks_job.h \ sa/eap/eap_method.c sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ @@ -72,6 +77,7 @@ sa/ike_sa.c sa/ike_sa.h \ sa/ike_sa_id.c sa/ike_sa_id.h \ sa/keymat.h sa/keymat.c \ sa/ike_sa_manager.c sa/ike_sa_manager.h \ +sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ @@ -97,6 +103,7 @@ sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ +sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h @@ -238,4 +245,3 @@ LOCAL_PRELINK_MODULE := false LOCAL_SHARED_LIBRARIES += libstrongswan libhydra include $(BUILD_SHARED_LIBRARY) - diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index e98f5e137..cd81a5eee 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -1,6 +1,10 @@ ipseclib_LTLIBRARIES = libcharon.la libcharon_la_SOURCES = \ +attributes/attributes.c attributes/attributes.h \ +attributes/attribute_provider.h attributes/attribute_handler.h \ +attributes/attribute_manager.c attributes/attribute_manager.h \ +attributes/mem_pool.c attributes/mem_pool.h \ bus/bus.c bus/bus.h \ bus/listeners/listener.h \ bus/listeners/logger.h \ @@ -60,6 +64,7 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ +processing/jobs/initiate_tasks_job.c processing/jobs/initiate_tasks_job.h \ sa/eap/eap_method.c sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ @@ -70,6 +75,7 @@ sa/ike_sa.c sa/ike_sa.h \ sa/ike_sa_id.c sa/ike_sa_id.h \ sa/keymat.h sa/keymat.c \ sa/ike_sa_manager.c sa/ike_sa_manager.h \ +sa/child_sa_manager.c sa/child_sa_manager.h \ sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h \ sa/trap_manager.c sa/trap_manager.h \ @@ -96,6 +102,7 @@ sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ +sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h endif @@ -203,6 +210,20 @@ if MONOLITHIC endif endif +if USE_CONNMARK + SUBDIRS += plugins/connmark +if MONOLITHIC + libcharon_la_LIBADD += plugins/connmark/libstrongswan-connmark.la +endif +endif + +if USE_FORECAST + SUBDIRS += plugins/forecast +if MONOLITHIC + libcharon_la_LIBADD += plugins/forecast/libstrongswan-forecast.la +endif +endif + if USE_FARP SUBDIRS += plugins/farp if MONOLITHIC @@ -595,13 +616,6 @@ if MONOLITHIC endif endif -if USE_UNIT_TESTS - SUBDIRS += plugins/unit_tester -if MONOLITHIC - libcharon_la_LIBADD += plugins/unit_tester/libstrongswan-unit-tester.la -endif -endif - if USE_XAUTH_GENERIC SUBDIRS += plugins/xauth_generic if MONOLITHIC @@ -629,3 +643,29 @@ if MONOLITHIC libcharon_la_LIBADD += plugins/xauth_noauth/libstrongswan-xauth-noauth.la endif endif + +if USE_RESOLVE + SUBDIRS += plugins/resolve +if MONOLITHIC + libcharon_la_LIBADD += plugins/resolve/libstrongswan-resolve.la +endif +endif + +if USE_ATTR + SUBDIRS += plugins/attr +if MONOLITHIC + libcharon_la_LIBADD += plugins/attr/libstrongswan-attr.la +endif +endif + +if USE_ATTR_SQL + SUBDIRS += plugins/attr_sql +if MONOLITHIC + libcharon_la_LIBADD += plugins/attr_sql/libstrongswan-attr-sql.la +endif +endif + +if MONOLITHIC + SUBDIRS += . +endif +SUBDIRS += tests diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in index 4d89794b5..3d425e0b4 100644 --- a/src/libcharon/Makefile.in +++ b/src/libcharon/Makefile.in @@ -98,6 +98,7 @@ host_triplet = @host@ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ +@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_reauth_complete.c sa/ikev2/tasks/ike_reauth_complete.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_auth_lifetime.c sa/ikev2/tasks/ike_auth_lifetime.h \ @USE_IKEV2_TRUE@sa/ikev2/tasks/ike_vendor.c sa/ikev2/tasks/ike_vendor.h @@ -146,124 +147,132 @@ host_triplet = @host@ @MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE@am__append_11 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la @USE_SOCKET_WIN_TRUE@am__append_12 = plugins/socket_win @MONOLITHIC_TRUE@@USE_SOCKET_WIN_TRUE@am__append_13 = plugins/socket_win/libstrongswan-socket-win.la -@USE_FARP_TRUE@am__append_14 = plugins/farp -@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_15 = plugins/farp/libstrongswan-farp.la -@USE_STROKE_TRUE@am__append_16 = plugins/stroke -@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_17 = plugins/stroke/libstrongswan-stroke.la -@USE_VICI_TRUE@am__append_18 = plugins/vici -@MONOLITHIC_TRUE@@USE_VICI_TRUE@am__append_19 = plugins/vici/libstrongswan-vici.la -@USE_SMP_TRUE@am__append_20 = plugins/smp -@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_21 = plugins/smp/libstrongswan-smp.la -@USE_SQL_TRUE@am__append_22 = plugins/sql -@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_23 = plugins/sql/libstrongswan-sql.la -@USE_DNSCERT_TRUE@am__append_24 = plugins/dnscert -@MONOLITHIC_TRUE@@USE_DNSCERT_TRUE@am__append_25 = plugins/dnscert/libstrongswan-dnscert.la -@USE_IPSECKEY_TRUE@am__append_26 = plugins/ipseckey -@MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE@am__append_27 = plugins/ipseckey/libstrongswan-ipseckey.la -@USE_UPDOWN_TRUE@am__append_28 = plugins/updown -@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_29 = plugins/updown/libstrongswan-updown.la -@USE_EXT_AUTH_TRUE@am__append_30 = plugins/ext_auth -@MONOLITHIC_TRUE@@USE_EXT_AUTH_TRUE@am__append_31 = plugins/ext_auth/libstrongswan-ext-auth.la -@USE_EAP_IDENTITY_TRUE@am__append_32 = plugins/eap_identity -@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_33 = plugins/eap_identity/libstrongswan-eap-identity.la -@USE_EAP_SIM_TRUE@am__append_34 = plugins/eap_sim -@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_35 = plugins/eap_sim/libstrongswan-eap-sim.la -@USE_EAP_SIM_FILE_TRUE@am__append_36 = plugins/eap_sim_file -@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_37 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la -@USE_EAP_SIM_PCSC_TRUE@am__append_38 = plugins/eap_sim_pcsc -@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_39 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la -@USE_EAP_SIMAKA_SQL_TRUE@am__append_40 = plugins/eap_simaka_sql -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_41 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la -@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_42 = plugins/eap_simaka_pseudonym -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_43 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la -@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_44 = plugins/eap_simaka_reauth -@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_45 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la -@USE_EAP_AKA_TRUE@am__append_46 = plugins/eap_aka -@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_47 = plugins/eap_aka/libstrongswan-eap-aka.la -@USE_EAP_AKA_3GPP2_TRUE@am__append_48 = plugins/eap_aka_3gpp2 -@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_49 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la -@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_50 = $(top_builddir)/src/libsimaka/libsimaka.la -@USE_EAP_MD5_TRUE@am__append_51 = plugins/eap_md5 -@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_52 = plugins/eap_md5/libstrongswan-eap-md5.la -@USE_EAP_GTC_TRUE@am__append_53 = plugins/eap_gtc -@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_54 = plugins/eap_gtc/libstrongswan-eap-gtc.la -@USE_EAP_MSCHAPV2_TRUE@am__append_55 = plugins/eap_mschapv2 -@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_56 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la -@USE_EAP_DYNAMIC_TRUE@am__append_57 = plugins/eap_dynamic -@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_58 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la -@USE_EAP_RADIUS_TRUE@am__append_59 = plugins/eap_radius -@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_60 = plugins/eap_radius/libstrongswan-eap-radius.la -@USE_EAP_TLS_TRUE@am__append_61 = plugins/eap_tls -@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_62 = plugins/eap_tls/libstrongswan-eap-tls.la -@USE_EAP_TTLS_TRUE@am__append_63 = plugins/eap_ttls -@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_64 = plugins/eap_ttls/libstrongswan-eap-ttls.la -@USE_EAP_PEAP_TRUE@am__append_65 = plugins/eap_peap -@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_66 = plugins/eap_peap/libstrongswan-eap-peap.la -@USE_EAP_TNC_TRUE@am__append_67 = plugins/eap_tnc -@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_68 = plugins/eap_tnc/libstrongswan-eap-tnc.la -@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_69 = $(top_builddir)/src/libtls/libtls.la -@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_70 = $(top_builddir)/src/libradius/libradius.la -@USE_TNC_IFMAP_TRUE@am__append_71 = plugins/tnc_ifmap -@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_72 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la -@USE_TNC_PDP_TRUE@am__append_73 = plugins/tnc_pdp -@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_74 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la -@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_75 = $(top_builddir)/src/libtnccs/libtnccs.la -@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv -@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_77 = plugins/medsrv/libstrongswan-medsrv.la -@USE_MEDCLI_TRUE@am__append_78 = plugins/medcli -@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli/libstrongswan-medcli.la -@USE_DHCP_TRUE@am__append_80 = plugins/dhcp -@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_81 = plugins/dhcp/libstrongswan-dhcp.la -@USE_OSX_ATTR_TRUE@am__append_82 = plugins/osx_attr -@MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_83 = plugins/osx_attr/libstrongswan-osx-attr.la -@USE_ANDROID_DNS_TRUE@am__append_84 = plugins/android_dns -@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_85 = plugins/android_dns/libstrongswan-android-dns.la -@USE_ANDROID_LOG_TRUE@am__append_86 = plugins/android_log -@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_87 = plugins/android_log/libstrongswan-android-log.la -@USE_MAEMO_TRUE@am__append_88 = plugins/maemo -@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_89 = plugins/maemo/libstrongswan-maemo.la -@USE_HA_TRUE@am__append_90 = plugins/ha -@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_91 = plugins/ha/libstrongswan-ha.la -@USE_KERNEL_LIBIPSEC_TRUE@am__append_92 = plugins/kernel_libipsec -@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_93 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la -@USE_KERNEL_WFP_TRUE@am__append_94 = plugins/kernel_wfp -@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_95 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la -@USE_KERNEL_IPH_TRUE@am__append_96 = plugins/kernel_iph -@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_97 = plugins/kernel_iph/libstrongswan-kernel-iph.la -@USE_WHITELIST_TRUE@am__append_98 = plugins/whitelist -@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_99 = plugins/whitelist/libstrongswan-whitelist.la -@USE_LOOKIP_TRUE@am__append_100 = plugins/lookip -@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_101 = plugins/lookip/libstrongswan-lookip.la -@USE_ERROR_NOTIFY_TRUE@am__append_102 = plugins/error_notify -@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_103 = plugins/error_notify/libstrongswan-error-notify.la -@USE_CERTEXPIRE_TRUE@am__append_104 = plugins/certexpire -@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_105 = plugins/certexpire/libstrongswan-certexpire.la -@USE_SYSTIME_FIX_TRUE@am__append_106 = plugins/systime_fix -@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_107 = plugins/systime_fix/libstrongswan-systime-fix.la -@USE_LED_TRUE@am__append_108 = plugins/led -@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_109 = plugins/led/libstrongswan-led.la -@USE_DUPLICHECK_TRUE@am__append_110 = plugins/duplicheck -@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_111 = plugins/duplicheck/libstrongswan-duplicheck.la -@USE_COUPLING_TRUE@am__append_112 = plugins/coupling -@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_113 = plugins/coupling/libstrongswan-coupling.la -@USE_RADATTR_TRUE@am__append_114 = plugins/radattr -@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_115 = plugins/radattr/libstrongswan-radattr.la -@USE_UCI_TRUE@am__append_116 = plugins/uci -@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_117 = plugins/uci/libstrongswan-uci.la -@USE_ADDRBLOCK_TRUE@am__append_118 = plugins/addrblock -@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_119 = plugins/addrblock/libstrongswan-addrblock.la -@USE_UNITY_TRUE@am__append_120 = plugins/unity -@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_121 = plugins/unity/libstrongswan-unity.la -@USE_UNIT_TESTS_TRUE@am__append_122 = plugins/unit_tester -@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_123 = plugins/unit_tester/libstrongswan-unit-tester.la -@USE_XAUTH_GENERIC_TRUE@am__append_124 = plugins/xauth_generic -@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_125 = plugins/xauth_generic/libstrongswan-xauth-generic.la -@USE_XAUTH_EAP_TRUE@am__append_126 = plugins/xauth_eap -@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_127 = plugins/xauth_eap/libstrongswan-xauth-eap.la -@USE_XAUTH_PAM_TRUE@am__append_128 = plugins/xauth_pam -@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_129 = plugins/xauth_pam/libstrongswan-xauth-pam.la -@USE_XAUTH_NOAUTH_TRUE@am__append_130 = plugins/xauth_noauth -@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_131 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la +@USE_CONNMARK_TRUE@am__append_14 = plugins/connmark +@MONOLITHIC_TRUE@@USE_CONNMARK_TRUE@am__append_15 = plugins/connmark/libstrongswan-connmark.la +@USE_FORECAST_TRUE@am__append_16 = plugins/forecast +@MONOLITHIC_TRUE@@USE_FORECAST_TRUE@am__append_17 = plugins/forecast/libstrongswan-forecast.la +@USE_FARP_TRUE@am__append_18 = plugins/farp +@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_19 = plugins/farp/libstrongswan-farp.la +@USE_STROKE_TRUE@am__append_20 = plugins/stroke +@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_21 = plugins/stroke/libstrongswan-stroke.la +@USE_VICI_TRUE@am__append_22 = plugins/vici +@MONOLITHIC_TRUE@@USE_VICI_TRUE@am__append_23 = plugins/vici/libstrongswan-vici.la +@USE_SMP_TRUE@am__append_24 = plugins/smp +@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_25 = plugins/smp/libstrongswan-smp.la +@USE_SQL_TRUE@am__append_26 = plugins/sql +@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_27 = plugins/sql/libstrongswan-sql.la +@USE_DNSCERT_TRUE@am__append_28 = plugins/dnscert +@MONOLITHIC_TRUE@@USE_DNSCERT_TRUE@am__append_29 = plugins/dnscert/libstrongswan-dnscert.la +@USE_IPSECKEY_TRUE@am__append_30 = plugins/ipseckey +@MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE@am__append_31 = plugins/ipseckey/libstrongswan-ipseckey.la +@USE_UPDOWN_TRUE@am__append_32 = plugins/updown +@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_33 = plugins/updown/libstrongswan-updown.la +@USE_EXT_AUTH_TRUE@am__append_34 = plugins/ext_auth +@MONOLITHIC_TRUE@@USE_EXT_AUTH_TRUE@am__append_35 = plugins/ext_auth/libstrongswan-ext-auth.la +@USE_EAP_IDENTITY_TRUE@am__append_36 = plugins/eap_identity +@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_37 = plugins/eap_identity/libstrongswan-eap-identity.la +@USE_EAP_SIM_TRUE@am__append_38 = plugins/eap_sim +@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_39 = plugins/eap_sim/libstrongswan-eap-sim.la +@USE_EAP_SIM_FILE_TRUE@am__append_40 = plugins/eap_sim_file +@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_41 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la +@USE_EAP_SIM_PCSC_TRUE@am__append_42 = plugins/eap_sim_pcsc +@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_43 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la +@USE_EAP_SIMAKA_SQL_TRUE@am__append_44 = plugins/eap_simaka_sql +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_45 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la +@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_46 = plugins/eap_simaka_pseudonym +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_47 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la +@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_48 = plugins/eap_simaka_reauth +@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_49 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la +@USE_EAP_AKA_TRUE@am__append_50 = plugins/eap_aka +@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_51 = plugins/eap_aka/libstrongswan-eap-aka.la +@USE_EAP_AKA_3GPP2_TRUE@am__append_52 = plugins/eap_aka_3gpp2 +@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_53 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la +@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_54 = $(top_builddir)/src/libsimaka/libsimaka.la +@USE_EAP_MD5_TRUE@am__append_55 = plugins/eap_md5 +@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_56 = plugins/eap_md5/libstrongswan-eap-md5.la +@USE_EAP_GTC_TRUE@am__append_57 = plugins/eap_gtc +@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_58 = plugins/eap_gtc/libstrongswan-eap-gtc.la +@USE_EAP_MSCHAPV2_TRUE@am__append_59 = plugins/eap_mschapv2 +@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_60 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la +@USE_EAP_DYNAMIC_TRUE@am__append_61 = plugins/eap_dynamic +@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_62 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la +@USE_EAP_RADIUS_TRUE@am__append_63 = plugins/eap_radius +@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_64 = plugins/eap_radius/libstrongswan-eap-radius.la +@USE_EAP_TLS_TRUE@am__append_65 = plugins/eap_tls +@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_66 = plugins/eap_tls/libstrongswan-eap-tls.la +@USE_EAP_TTLS_TRUE@am__append_67 = plugins/eap_ttls +@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_68 = plugins/eap_ttls/libstrongswan-eap-ttls.la +@USE_EAP_PEAP_TRUE@am__append_69 = plugins/eap_peap +@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_70 = plugins/eap_peap/libstrongswan-eap-peap.la +@USE_EAP_TNC_TRUE@am__append_71 = plugins/eap_tnc +@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_72 = plugins/eap_tnc/libstrongswan-eap-tnc.la +@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_73 = $(top_builddir)/src/libtls/libtls.la +@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_74 = $(top_builddir)/src/libradius/libradius.la +@USE_TNC_IFMAP_TRUE@am__append_75 = plugins/tnc_ifmap +@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_76 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la +@USE_TNC_PDP_TRUE@am__append_77 = plugins/tnc_pdp +@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_78 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la +@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_79 = $(top_builddir)/src/libtnccs/libtnccs.la +@USE_MEDSRV_TRUE@am__append_80 = plugins/medsrv +@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_81 = plugins/medsrv/libstrongswan-medsrv.la +@USE_MEDCLI_TRUE@am__append_82 = plugins/medcli +@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_83 = plugins/medcli/libstrongswan-medcli.la +@USE_DHCP_TRUE@am__append_84 = plugins/dhcp +@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_85 = plugins/dhcp/libstrongswan-dhcp.la +@USE_OSX_ATTR_TRUE@am__append_86 = plugins/osx_attr +@MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_87 = plugins/osx_attr/libstrongswan-osx-attr.la +@USE_ANDROID_DNS_TRUE@am__append_88 = plugins/android_dns +@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_89 = plugins/android_dns/libstrongswan-android-dns.la +@USE_ANDROID_LOG_TRUE@am__append_90 = plugins/android_log +@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_91 = plugins/android_log/libstrongswan-android-log.la +@USE_MAEMO_TRUE@am__append_92 = plugins/maemo +@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_93 = plugins/maemo/libstrongswan-maemo.la +@USE_HA_TRUE@am__append_94 = plugins/ha +@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_95 = plugins/ha/libstrongswan-ha.la +@USE_KERNEL_LIBIPSEC_TRUE@am__append_96 = plugins/kernel_libipsec +@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_97 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la +@USE_KERNEL_WFP_TRUE@am__append_98 = plugins/kernel_wfp +@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_99 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la +@USE_KERNEL_IPH_TRUE@am__append_100 = plugins/kernel_iph +@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_101 = plugins/kernel_iph/libstrongswan-kernel-iph.la +@USE_WHITELIST_TRUE@am__append_102 = plugins/whitelist +@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_103 = plugins/whitelist/libstrongswan-whitelist.la +@USE_LOOKIP_TRUE@am__append_104 = plugins/lookip +@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_105 = plugins/lookip/libstrongswan-lookip.la +@USE_ERROR_NOTIFY_TRUE@am__append_106 = plugins/error_notify +@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_107 = plugins/error_notify/libstrongswan-error-notify.la +@USE_CERTEXPIRE_TRUE@am__append_108 = plugins/certexpire +@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_109 = plugins/certexpire/libstrongswan-certexpire.la +@USE_SYSTIME_FIX_TRUE@am__append_110 = plugins/systime_fix +@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_111 = plugins/systime_fix/libstrongswan-systime-fix.la +@USE_LED_TRUE@am__append_112 = plugins/led +@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_113 = plugins/led/libstrongswan-led.la +@USE_DUPLICHECK_TRUE@am__append_114 = plugins/duplicheck +@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_115 = plugins/duplicheck/libstrongswan-duplicheck.la +@USE_COUPLING_TRUE@am__append_116 = plugins/coupling +@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_117 = plugins/coupling/libstrongswan-coupling.la +@USE_RADATTR_TRUE@am__append_118 = plugins/radattr +@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_119 = plugins/radattr/libstrongswan-radattr.la +@USE_UCI_TRUE@am__append_120 = plugins/uci +@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_121 = plugins/uci/libstrongswan-uci.la +@USE_ADDRBLOCK_TRUE@am__append_122 = plugins/addrblock +@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_123 = plugins/addrblock/libstrongswan-addrblock.la +@USE_UNITY_TRUE@am__append_124 = plugins/unity +@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_125 = plugins/unity/libstrongswan-unity.la +@USE_XAUTH_GENERIC_TRUE@am__append_126 = plugins/xauth_generic +@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_127 = plugins/xauth_generic/libstrongswan-xauth-generic.la +@USE_XAUTH_EAP_TRUE@am__append_128 = plugins/xauth_eap +@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_129 = plugins/xauth_eap/libstrongswan-xauth-eap.la +@USE_XAUTH_PAM_TRUE@am__append_130 = plugins/xauth_pam +@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_131 = plugins/xauth_pam/libstrongswan-xauth-pam.la +@USE_XAUTH_NOAUTH_TRUE@am__append_132 = plugins/xauth_noauth +@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_133 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la +@USE_RESOLVE_TRUE@am__append_134 = plugins/resolve +@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_135 = plugins/resolve/libstrongswan-resolve.la +@USE_ATTR_TRUE@am__append_136 = plugins/attr +@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_137 = plugins/attr/libstrongswan-attr.la +@USE_ATTR_SQL_TRUE@am__append_138 = plugins/attr_sql +@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_139 = plugins/attr_sql/libstrongswan-attr-sql.la subdir = src/libcharon DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -325,12 +334,12 @@ libcharon_la_DEPENDENCIES = \ $(am__append_29) $(am__append_31) $(am__append_33) \ $(am__append_35) $(am__append_37) $(am__append_39) \ $(am__append_41) $(am__append_43) $(am__append_45) \ - $(am__append_47) $(am__append_49) $(am__append_50) \ - $(am__append_52) $(am__append_54) $(am__append_56) \ + $(am__append_47) $(am__append_49) $(am__append_51) \ + $(am__append_53) $(am__append_54) $(am__append_56) \ $(am__append_58) $(am__append_60) $(am__append_62) \ $(am__append_64) $(am__append_66) $(am__append_68) \ - $(am__append_69) $(am__append_70) $(am__append_72) \ - $(am__append_74) $(am__append_75) $(am__append_77) \ + $(am__append_70) $(am__append_72) $(am__append_73) \ + $(am__append_74) $(am__append_76) $(am__append_78) \ $(am__append_79) $(am__append_81) $(am__append_83) \ $(am__append_85) $(am__append_87) $(am__append_89) \ $(am__append_91) $(am__append_93) $(am__append_95) \ @@ -339,8 +348,14 @@ libcharon_la_DEPENDENCIES = \ $(am__append_109) $(am__append_111) $(am__append_113) \ $(am__append_115) $(am__append_117) $(am__append_119) \ $(am__append_121) $(am__append_123) $(am__append_125) \ - $(am__append_127) $(am__append_129) $(am__append_131) -am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ + $(am__append_127) $(am__append_129) $(am__append_131) \ + $(am__append_133) $(am__append_135) $(am__append_137) \ + $(am__append_139) +am__libcharon_la_SOURCES_DIST = attributes/attributes.c \ + attributes/attributes.h attributes/attribute_provider.h \ + attributes/attribute_handler.h attributes/attribute_manager.c \ + attributes/attribute_manager.h attributes/mem_pool.c \ + attributes/mem_pool.h bus/bus.c bus/bus.h \ bus/listeners/listener.h bus/listeners/logger.h \ bus/listeners/file_logger.c bus/listeners/file_logger.h \ config/backend_manager.c config/backend_manager.h \ @@ -421,7 +436,9 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ processing/jobs/roam_job.h processing/jobs/update_sa_job.c \ processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c \ - processing/jobs/inactivity_job.h sa/eap/eap_method.c \ + processing/jobs/inactivity_job.h \ + processing/jobs/initiate_tasks_job.c \ + processing/jobs/initiate_tasks_job.h sa/eap/eap_method.c \ sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ @@ -429,7 +446,8 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ sa/authenticator.c sa/authenticator.h sa/child_sa.c \ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \ sa/ike_sa_id.h sa/keymat.h sa/keymat.c sa/ike_sa_manager.c \ - sa/ike_sa_manager.h sa/task_manager.h sa/task_manager.c \ + sa/ike_sa_manager.h sa/child_sa_manager.c \ + sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \ sa/trap_manager.h sa/task.c sa/task.h sa/ikev2/keymat_v2.c \ sa/ikev2/keymat_v2.h sa/ikev2/task_manager_v2.c \ @@ -454,6 +472,8 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ + sa/ikev2/tasks/ike_reauth_complete.c \ + sa/ikev2/tasks/ike_reauth_complete.h \ sa/ikev2/tasks/ike_auth_lifetime.c \ sa/ikev2/tasks/ike_auth_lifetime.h sa/ikev2/tasks/ike_vendor.c \ sa/ikev2/tasks/ike_vendor.h sa/ikev1/keymat_v1.c \ @@ -514,6 +534,7 @@ am__dirstamp = $(am__leading_dot)dirstamp @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_mobike.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_rekey.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_reauth.lo \ +@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_reauth_complete.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_auth_lifetime.lo \ @USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_vendor.lo @USE_IKEV1_TRUE@am__objects_2 = sa/ikev1/keymat_v1.lo \ @@ -543,7 +564,9 @@ am__dirstamp = $(am__leading_dot)dirstamp @USE_ME_TRUE@ sa/ikev2/connect_manager.lo \ @USE_ME_TRUE@ sa/ikev2/mediation_manager.lo \ @USE_ME_TRUE@ sa/ikev2/tasks/ike_me.lo -am_libcharon_la_OBJECTS = bus/bus.lo bus/listeners/file_logger.lo \ +am_libcharon_la_OBJECTS = attributes/attributes.lo \ + attributes/attribute_manager.lo attributes/mem_pool.lo \ + bus/bus.lo bus/listeners/file_logger.lo \ config/backend_manager.lo config/child_cfg.lo \ config/ike_cfg.lo config/peer_cfg.lo config/proposal.lo \ control/controller.lo daemon.lo encoding/generator.lo \ @@ -587,13 +610,14 @@ am_libcharon_la_OBJECTS = bus/bus.lo bus/listeners/file_logger.lo \ processing/jobs/send_keepalive_job.lo \ processing/jobs/start_action_job.lo \ processing/jobs/roam_job.lo processing/jobs/update_sa_job.lo \ - processing/jobs/inactivity_job.lo sa/eap/eap_method.lo \ + processing/jobs/inactivity_job.lo \ + processing/jobs/initiate_tasks_job.lo sa/eap/eap_method.lo \ sa/eap/eap_manager.lo sa/xauth/xauth_method.lo \ sa/xauth/xauth_manager.lo sa/authenticator.lo sa/child_sa.lo \ sa/ike_sa.lo sa/ike_sa_id.lo sa/keymat.lo sa/ike_sa_manager.lo \ - sa/task_manager.lo sa/shunt_manager.lo sa/trap_manager.lo \ - sa/task.lo $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) + sa/child_sa_manager.lo sa/task_manager.lo sa/shunt_manager.lo \ + sa/trap_manager.lo sa/task.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -676,11 +700,11 @@ am__define_uniq_tagged_files = \ ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \ - plugins/socket_dynamic plugins/socket_win plugins/farp \ - plugins/stroke plugins/vici plugins/smp plugins/sql \ - plugins/dnscert plugins/ipseckey plugins/updown \ - plugins/ext_auth plugins/eap_identity plugins/eap_sim \ - plugins/eap_sim_file plugins/eap_sim_pcsc \ + plugins/socket_dynamic plugins/socket_win plugins/connmark \ + plugins/forecast plugins/farp plugins/stroke plugins/vici \ + plugins/smp plugins/sql plugins/dnscert plugins/ipseckey \ + plugins/updown plugins/ext_auth plugins/eap_identity \ + plugins/eap_sim plugins/eap_sim_file plugins/eap_sim_pcsc \ plugins/eap_simaka_sql plugins/eap_simaka_pseudonym \ plugins/eap_simaka_reauth plugins/eap_aka \ plugins/eap_aka_3gpp2 plugins/eap_md5 plugins/eap_gtc \ @@ -694,8 +718,9 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \ plugins/error_notify plugins/certexpire plugins/systime_fix \ plugins/led plugins/duplicheck plugins/coupling \ plugins/radattr plugins/uci plugins/addrblock plugins/unity \ - plugins/unit_tester plugins/xauth_generic plugins/xauth_eap \ - plugins/xauth_pam plugins/xauth_noauth + plugins/xauth_generic plugins/xauth_eap plugins/xauth_pam \ + plugins/xauth_noauth plugins/resolve plugins/attr \ + plugins/attr_sql tests DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -747,6 +772,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -807,10 +833,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -884,6 +912,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ @@ -943,16 +973,20 @@ urandom_device = @urandom_device@ xml_CFLAGS = @xml_CFLAGS@ xml_LIBS = @xml_LIBS@ ipseclib_LTLIBRARIES = libcharon.la -libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ - bus/listeners/logger.h bus/listeners/file_logger.c \ - bus/listeners/file_logger.h config/backend_manager.c \ - 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 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 \ +libcharon_la_SOURCES = attributes/attributes.c attributes/attributes.h \ + attributes/attribute_provider.h attributes/attribute_handler.h \ + attributes/attribute_manager.c attributes/attribute_manager.h \ + attributes/mem_pool.c attributes/mem_pool.h bus/bus.c \ + bus/bus.h bus/listeners/listener.h bus/listeners/logger.h \ + bus/listeners/file_logger.c bus/listeners/file_logger.h \ + config/backend_manager.c 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 \ + 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 \ @@ -1023,7 +1057,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ processing/jobs/roam_job.h processing/jobs/update_sa_job.c \ processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c \ - processing/jobs/inactivity_job.h sa/eap/eap_method.c \ + processing/jobs/inactivity_job.h \ + processing/jobs/initiate_tasks_job.c \ + processing/jobs/initiate_tasks_job.h sa/eap/eap_method.c \ sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ @@ -1031,7 +1067,8 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \ sa/authenticator.c sa/authenticator.h sa/child_sa.c \ sa/child_sa.h sa/ike_sa.c sa/ike_sa.h sa/ike_sa_id.c \ sa/ike_sa_id.h sa/keymat.h sa/keymat.c sa/ike_sa_manager.c \ - sa/ike_sa_manager.h sa/task_manager.h sa/task_manager.c \ + sa/ike_sa_manager.h sa/child_sa_manager.c \ + sa/child_sa_manager.h sa/task_manager.h sa/task_manager.c \ sa/shunt_manager.c sa/shunt_manager.h sa/trap_manager.c \ sa/trap_manager.h sa/task.c sa/task.h $(am__append_1) \ $(am__append_2) $(am__append_3) $(am__append_5) @@ -1057,12 +1094,12 @@ libcharon_la_LIBADD = \ $(am__append_33) $(am__append_35) $(am__append_37) \ $(am__append_39) $(am__append_41) $(am__append_43) \ $(am__append_45) $(am__append_47) $(am__append_49) \ - $(am__append_50) $(am__append_52) $(am__append_54) \ + $(am__append_51) $(am__append_53) $(am__append_54) \ $(am__append_56) $(am__append_58) $(am__append_60) \ $(am__append_62) $(am__append_64) $(am__append_66) \ - $(am__append_68) $(am__append_69) $(am__append_70) \ - $(am__append_72) $(am__append_74) $(am__append_75) \ - $(am__append_77) $(am__append_79) $(am__append_81) \ + $(am__append_68) $(am__append_70) $(am__append_72) \ + $(am__append_73) $(am__append_74) $(am__append_76) \ + $(am__append_78) $(am__append_79) $(am__append_81) \ $(am__append_83) $(am__append_85) $(am__append_87) \ $(am__append_89) $(am__append_91) $(am__append_93) \ $(am__append_95) $(am__append_97) $(am__append_99) \ @@ -1071,7 +1108,8 @@ libcharon_la_LIBADD = \ $(am__append_113) $(am__append_115) $(am__append_117) \ $(am__append_119) $(am__append_121) $(am__append_123) \ $(am__append_125) $(am__append_127) $(am__append_129) \ - $(am__append_131) + $(am__append_131) $(am__append_133) $(am__append_135) \ + $(am__append_137) $(am__append_139) EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \ @MONOLITHIC_FALSE@ $(am__append_10) $(am__append_12) \ @@ -1084,13 +1122,13 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_38) $(am__append_40) \ @MONOLITHIC_FALSE@ $(am__append_42) $(am__append_44) \ @MONOLITHIC_FALSE@ $(am__append_46) $(am__append_48) \ -@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_53) \ +@MONOLITHIC_FALSE@ $(am__append_50) $(am__append_52) \ @MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \ @MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61) \ @MONOLITHIC_FALSE@ $(am__append_63) $(am__append_65) \ -@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_71) \ -@MONOLITHIC_FALSE@ $(am__append_73) $(am__append_76) \ -@MONOLITHIC_FALSE@ $(am__append_78) $(am__append_80) \ +@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_69) \ +@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_75) \ +@MONOLITHIC_FALSE@ $(am__append_77) $(am__append_80) \ @MONOLITHIC_FALSE@ $(am__append_82) $(am__append_84) \ @MONOLITHIC_FALSE@ $(am__append_86) $(am__append_88) \ @MONOLITHIC_FALSE@ $(am__append_90) $(am__append_92) \ @@ -1103,7 +1141,9 @@ EXTRA_DIST = Android.mk @MONOLITHIC_FALSE@ $(am__append_118) $(am__append_120) \ @MONOLITHIC_FALSE@ $(am__append_122) $(am__append_124) \ @MONOLITHIC_FALSE@ $(am__append_126) $(am__append_128) \ -@MONOLITHIC_FALSE@ $(am__append_130) +@MONOLITHIC_FALSE@ $(am__append_130) $(am__append_132) \ +@MONOLITHIC_FALSE@ $(am__append_134) $(am__append_136) \ +@MONOLITHIC_FALSE@ $(am__append_138) tests # build optional plugins ######################## @@ -1118,13 +1158,13 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_38) $(am__append_40) \ @MONOLITHIC_TRUE@ $(am__append_42) $(am__append_44) \ @MONOLITHIC_TRUE@ $(am__append_46) $(am__append_48) \ -@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_53) \ +@MONOLITHIC_TRUE@ $(am__append_50) $(am__append_52) \ @MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \ @MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61) \ @MONOLITHIC_TRUE@ $(am__append_63) $(am__append_65) \ -@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_71) \ -@MONOLITHIC_TRUE@ $(am__append_73) $(am__append_76) \ -@MONOLITHIC_TRUE@ $(am__append_78) $(am__append_80) \ +@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_69) \ +@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_75) \ +@MONOLITHIC_TRUE@ $(am__append_77) $(am__append_80) \ @MONOLITHIC_TRUE@ $(am__append_82) $(am__append_84) \ @MONOLITHIC_TRUE@ $(am__append_86) $(am__append_88) \ @MONOLITHIC_TRUE@ $(am__append_90) $(am__append_92) \ @@ -1137,7 +1177,9 @@ EXTRA_DIST = Android.mk @MONOLITHIC_TRUE@ $(am__append_118) $(am__append_120) \ @MONOLITHIC_TRUE@ $(am__append_122) $(am__append_124) \ @MONOLITHIC_TRUE@ $(am__append_126) $(am__append_128) \ -@MONOLITHIC_TRUE@ $(am__append_130) +@MONOLITHIC_TRUE@ $(am__append_130) $(am__append_132) \ +@MONOLITHIC_TRUE@ $(am__append_134) $(am__append_136) \ +@MONOLITHIC_TRUE@ $(am__append_138) . tests all: all-recursive .SUFFIXES: @@ -1207,6 +1249,18 @@ clean-ipseclibLTLIBRARIES: echo rm -f $${locs}; \ rm -f $${locs}; \ } +attributes/$(am__dirstamp): + @$(MKDIR_P) attributes + @: > attributes/$(am__dirstamp) +attributes/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) attributes/$(DEPDIR) + @: > attributes/$(DEPDIR)/$(am__dirstamp) +attributes/attributes.lo: attributes/$(am__dirstamp) \ + attributes/$(DEPDIR)/$(am__dirstamp) +attributes/attribute_manager.lo: attributes/$(am__dirstamp) \ + attributes/$(DEPDIR)/$(am__dirstamp) +attributes/mem_pool.lo: attributes/$(am__dirstamp) \ + attributes/$(DEPDIR)/$(am__dirstamp) bus/$(am__dirstamp): @$(MKDIR_P) bus @: > bus/$(am__dirstamp) @@ -1389,6 +1443,9 @@ processing/jobs/update_sa_job.lo: processing/jobs/$(am__dirstamp) \ processing/jobs/$(DEPDIR)/$(am__dirstamp) processing/jobs/inactivity_job.lo: processing/jobs/$(am__dirstamp) \ processing/jobs/$(DEPDIR)/$(am__dirstamp) +processing/jobs/initiate_tasks_job.lo: \ + processing/jobs/$(am__dirstamp) \ + processing/jobs/$(DEPDIR)/$(am__dirstamp) sa/eap/$(am__dirstamp): @$(MKDIR_P) sa/eap @: > sa/eap/$(am__dirstamp) @@ -1421,6 +1478,8 @@ sa/ike_sa.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/ike_sa_id.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/keymat.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/ike_sa_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) +sa/child_sa_manager.lo: sa/$(am__dirstamp) \ + sa/$(DEPDIR)/$(am__dirstamp) sa/task_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/shunt_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) sa/trap_manager.lo: sa/$(am__dirstamp) sa/$(DEPDIR)/$(am__dirstamp) @@ -1484,6 +1543,8 @@ sa/ikev2/tasks/ike_rekey.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_reauth.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) +sa/ikev2/tasks/ike_reauth_complete.lo: sa/ikev2/tasks/$(am__dirstamp) \ + sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_auth_lifetime.lo: sa/ikev2/tasks/$(am__dirstamp) \ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp) sa/ikev2/tasks/ike_vendor.lo: sa/ikev2/tasks/$(am__dirstamp) \ @@ -1574,6 +1635,8 @@ libcharon.la: $(libcharon_la_OBJECTS) $(libcharon_la_DEPENDENCIES) $(EXTRA_libch mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f attributes/*.$(OBJEXT) + -rm -f attributes/*.lo -rm -f bus/*.$(OBJEXT) -rm -f bus/*.lo -rm -f bus/listeners/*.$(OBJEXT) @@ -1615,6 +1678,9 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@attributes/$(DEPDIR)/attribute_manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@attributes/$(DEPDIR)/attributes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@attributes/$(DEPDIR)/mem_pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bus/$(DEPDIR)/bus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bus/listeners/$(DEPDIR)/file_logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@bus/listeners/$(DEPDIR)/sys_logger.Plo@am__quote@ @@ -1665,6 +1731,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/dpd_timeout_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/inactivity_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/initiate_mediation_job.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/initiate_tasks_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/mediation_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/migrate_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/process_message_job.Plo@am__quote@ @@ -1679,6 +1746,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@processing/jobs/$(DEPDIR)/update_sa_job.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/authenticator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/child_sa.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/child_sa_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/ike_sa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/ike_sa_id.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/ike_sa_manager.Plo@am__quote@ @@ -1730,6 +1798,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_mobike.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_natd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_reauth.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_reauth_complete.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_rekey.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_vendor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sa/xauth/$(DEPDIR)/xauth_manager.Plo@am__quote@ @@ -1764,6 +1833,7 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs + -rm -rf attributes/.libs attributes/_libs -rm -rf bus/.libs bus/_libs -rm -rf bus/listeners/.libs bus/listeners/_libs -rm -rf config/.libs config/_libs @@ -1971,6 +2041,8 @@ 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) + -rm -f attributes/$(DEPDIR)/$(am__dirstamp) + -rm -f attributes/$(am__dirstamp) -rm -f bus/$(DEPDIR)/$(am__dirstamp) -rm -f bus/$(am__dirstamp) -rm -f bus/listeners/$(DEPDIR)/$(am__dirstamp) @@ -2017,7 +2089,7 @@ clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive - -rm -rf ./$(DEPDIR) bus/$(DEPDIR) bus/listeners/$(DEPDIR) config/$(DEPDIR) control/$(DEPDIR) encoding/$(DEPDIR) encoding/payloads/$(DEPDIR) kernel/$(DEPDIR) network/$(DEPDIR) processing/jobs/$(DEPDIR) sa/$(DEPDIR) sa/eap/$(DEPDIR) sa/ikev1/$(DEPDIR) sa/ikev1/authenticators/$(DEPDIR) sa/ikev1/tasks/$(DEPDIR) sa/ikev2/$(DEPDIR) sa/ikev2/authenticators/$(DEPDIR) sa/ikev2/tasks/$(DEPDIR) sa/xauth/$(DEPDIR) + -rm -rf ./$(DEPDIR) attributes/$(DEPDIR) bus/$(DEPDIR) bus/listeners/$(DEPDIR) config/$(DEPDIR) control/$(DEPDIR) encoding/$(DEPDIR) encoding/payloads/$(DEPDIR) kernel/$(DEPDIR) network/$(DEPDIR) processing/jobs/$(DEPDIR) sa/$(DEPDIR) sa/eap/$(DEPDIR) sa/ikev1/$(DEPDIR) sa/ikev1/authenticators/$(DEPDIR) sa/ikev1/tasks/$(DEPDIR) sa/ikev2/$(DEPDIR) sa/ikev2/authenticators/$(DEPDIR) sa/ikev2/tasks/$(DEPDIR) sa/xauth/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -2063,7 +2135,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive - -rm -rf ./$(DEPDIR) bus/$(DEPDIR) bus/listeners/$(DEPDIR) config/$(DEPDIR) control/$(DEPDIR) encoding/$(DEPDIR) encoding/payloads/$(DEPDIR) kernel/$(DEPDIR) network/$(DEPDIR) processing/jobs/$(DEPDIR) sa/$(DEPDIR) sa/eap/$(DEPDIR) sa/ikev1/$(DEPDIR) sa/ikev1/authenticators/$(DEPDIR) sa/ikev1/tasks/$(DEPDIR) sa/ikev2/$(DEPDIR) sa/ikev2/authenticators/$(DEPDIR) sa/ikev2/tasks/$(DEPDIR) sa/xauth/$(DEPDIR) + -rm -rf ./$(DEPDIR) attributes/$(DEPDIR) bus/$(DEPDIR) bus/listeners/$(DEPDIR) config/$(DEPDIR) control/$(DEPDIR) encoding/$(DEPDIR) encoding/payloads/$(DEPDIR) kernel/$(DEPDIR) network/$(DEPDIR) processing/jobs/$(DEPDIR) sa/$(DEPDIR) sa/eap/$(DEPDIR) sa/ikev1/$(DEPDIR) sa/ikev1/authenticators/$(DEPDIR) sa/ikev1/tasks/$(DEPDIR) sa/ikev2/$(DEPDIR) sa/ikev2/authenticators/$(DEPDIR) sa/ikev2/tasks/$(DEPDIR) sa/xauth/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/libcharon/attributes/attribute_handler.h b/src/libcharon/attributes/attribute_handler.h new file mode 100644 index 000000000..3c14323a3 --- /dev/null +++ b/src/libcharon/attributes/attribute_handler.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup attribute_handler attribute_handler + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_HANDLER_H_ +#define ATTRIBUTE_HANDLER_H_ + +typedef struct attribute_handler_t attribute_handler_t; + +#include <sa/ike_sa.h> +#include <utils/chunk.h> +#include <collections/linked_list.h> + +#include "attributes.h" + +/** + * Interface to handle configuration payload attributes. + */ +struct attribute_handler_t { + + /** + * Handle a configuration attribute. + * + * After receiving a configuration attriubte, it is passed to each + * attribute handler until it is handled. + * + * @param ike_sa IKE_SA under which attribute is received + * @param type type of configuration attribute to handle + * @param data associated attribute data + * @return TRUE if attribute handled + */ + bool (*handle)(attribute_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); + + /** + * Release an attribute handled during handle(). + * + * A handler that handle()d an attribute gets a call to release() when the + * connection gets closed. Depending on the implementation, this is required + * to remove the attribute. + * + * @param ike_sa IKE_SA which releases attribute + * @param type type of configuration attribute to release + * @param data associated attribute data + */ + void (*release)(attribute_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); + + /** + * Enumerate attributes to request from a server. + * + * @param ike_sa IKE_SA to request attributes for + * @param vips list of virtual IPs (host_t*) we are requesting + * @return enumerator (configuration_attribute_type_t, chunk_t) + */ + enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this, + ike_sa_t *ike_sa, linked_list_t *vips); +}; + +#endif /** ATTRIBUTE_HANDLER_H_ @}*/ diff --git a/src/libcharon/attributes/attribute_manager.c b/src/libcharon/attributes/attribute_manager.c new file mode 100644 index 000000000..2ab7ed118 --- /dev/null +++ b/src/libcharon/attributes/attribute_manager.c @@ -0,0 +1,347 @@ +/* + * 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 "attribute_manager.h" + +#include <utils/debug.h> +#include <collections/linked_list.h> +#include <threading/rwlock.h> + +typedef struct private_attribute_manager_t private_attribute_manager_t; + +/** + * private data of attribute_manager + */ +struct private_attribute_manager_t { + + /** + * public functions + */ + attribute_manager_t public; + + /** + * list of registered providers + */ + linked_list_t *providers; + + /** + * list of registered handlers + */ + linked_list_t *handlers; + + /** + * rwlock provider list + */ + rwlock_t *lock; +}; + +/** + * Data to pass to enumerator filters + */ +typedef struct { + /** attribute group pools */ + linked_list_t *pools; + /** associated IKE_SA */ + ike_sa_t *ike_sa; + /** requesting/assigned virtual IPs */ + linked_list_t *vips; +} enum_data_t; + +METHOD(attribute_manager_t, acquire_address, host_t*, + private_attribute_manager_t *this, linked_list_t *pools, + ike_sa_t *ike_sa, host_t *requested) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + host_t *host = NULL; + + this->lock->read_lock(this->lock); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + host = current->acquire_address(current, pools, ike_sa, requested); + if (host) + { + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + return host; +} + +METHOD(attribute_manager_t, release_address, bool, + private_attribute_manager_t *this, linked_list_t *pools, host_t *address, + ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + attribute_provider_t *current; + bool found = FALSE; + + this->lock->read_lock(this->lock); + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->release_address(current, pools, address, ike_sa)) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + return found; +} + +/** + * inner enumerator constructor for responder attributes + */ +static enumerator_t *responder_enum_create(attribute_provider_t *provider, + enum_data_t *data) +{ + return provider->create_attribute_enumerator(provider, data->pools, + data->ike_sa, data->vips); +} + +METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*, + private_attribute_manager_t *this, linked_list_t *pools, + ike_sa_t *ike_sa, linked_list_t *vips) +{ + enum_data_t *data; + + INIT(data, + .pools = pools, + .ike_sa = ike_sa, + .vips = vips, + ); + this->lock->read_lock(this->lock); + return enumerator_create_cleaner( + enumerator_create_nested( + this->providers->create_enumerator(this->providers), + (void*)responder_enum_create, data, free), + (void*)this->lock->unlock, this->lock); +} + +METHOD(attribute_manager_t, add_provider, void, + private_attribute_manager_t *this, attribute_provider_t *provider) +{ + this->lock->write_lock(this->lock); + this->providers->insert_last(this->providers, provider); + this->lock->unlock(this->lock); +} + +METHOD(attribute_manager_t, remove_provider, void, + private_attribute_manager_t *this, attribute_provider_t *provider) +{ + this->lock->write_lock(this->lock); + this->providers->remove(this->providers, provider, NULL); + this->lock->unlock(this->lock); +} + +METHOD(attribute_manager_t, handle, attribute_handler_t*, + private_attribute_manager_t *this, ike_sa_t *ike_sa, + attribute_handler_t *handler, configuration_attribute_type_t type, + chunk_t data) +{ + enumerator_t *enumerator; + attribute_handler_t *current, *handled = NULL; + + this->lock->read_lock(this->lock); + + /* try to find the passed handler */ + enumerator = this->handlers->create_enumerator(this->handlers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current == handler && current->handle(current, ike_sa, type, data)) + { + handled = current; + break; + } + } + enumerator->destroy(enumerator); + if (!handled) + { /* handler requesting this attribute not found, try any other */ + enumerator = this->handlers->create_enumerator(this->handlers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->handle(current, ike_sa, type, data)) + { + handled = current; + break; + } + } + enumerator->destroy(enumerator); + } + this->lock->unlock(this->lock); + + if (!handled) + { + DBG1(DBG_CFG, "handling %N attribute failed", + configuration_attribute_type_names, type); + } + return handled; +} + +METHOD(attribute_manager_t, release, void, + private_attribute_manager_t *this, attribute_handler_t *handler, + ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) +{ + enumerator_t *enumerator; + attribute_handler_t *current; + + this->lock->read_lock(this->lock); + enumerator = this->handlers->create_enumerator(this->handlers); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current == handler) + { + current->release(current, ike_sa, type, data); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +/** + * Enumerator implementation to enumerate nested initiator attributes + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** back ref */ + private_attribute_manager_t *this; + /** currently processing handler */ + attribute_handler_t *handler; + /** outer enumerator over handlers */ + enumerator_t *outer; + /** inner enumerator over current handlers attributes */ + enumerator_t *inner; + /** IKE_SA to request attributes for */ + ike_sa_t *ike_sa; + /** virtual IPs we are requesting along with attriubutes */ + linked_list_t *vips; +} initiator_enumerator_t; + +/** + * Enumerator implementation for initiator attributes + */ +static bool initiator_enumerate(initiator_enumerator_t *this, + attribute_handler_t **handler, + configuration_attribute_type_t *type, + chunk_t *value) +{ + /* enumerate inner attributes using outer handler enumerator */ + while (!this->inner || !this->inner->enumerate(this->inner, type, value)) + { + if (!this->outer->enumerate(this->outer, &this->handler)) + { + return FALSE; + } + DESTROY_IF(this->inner); + this->inner = this->handler->create_attribute_enumerator(this->handler, + this->ike_sa, this->vips); + } + /* inject the handler as additional attribute */ + *handler = this->handler; + return TRUE; +} + +/** + * Cleanup function of initiator attribute enumerator + */ +static void initiator_destroy(initiator_enumerator_t *this) +{ + this->this->lock->unlock(this->this->lock); + this->outer->destroy(this->outer); + DESTROY_IF(this->inner); + free(this); +} + +METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*, + private_attribute_manager_t *this, ike_sa_t *ike_sa, linked_list_t *vips) +{ + initiator_enumerator_t *enumerator; + + this->lock->read_lock(this->lock); + + INIT(enumerator, + .public = { + .enumerate = (void*)initiator_enumerate, + .destroy = (void*)initiator_destroy, + }, + .this = this, + .ike_sa = ike_sa, + .vips = vips, + .outer = this->handlers->create_enumerator(this->handlers), + ); + return &enumerator->public; +} + +METHOD(attribute_manager_t, add_handler, void, + private_attribute_manager_t *this, attribute_handler_t *handler) +{ + this->lock->write_lock(this->lock); + this->handlers->insert_last(this->handlers, handler); + this->lock->unlock(this->lock); +} + +METHOD(attribute_manager_t, remove_handler, void, + private_attribute_manager_t *this, attribute_handler_t *handler) +{ + this->lock->write_lock(this->lock); + this->handlers->remove(this->handlers, handler, NULL); + this->lock->unlock(this->lock); +} + +METHOD(attribute_manager_t, destroy, void, + private_attribute_manager_t *this) +{ + this->providers->destroy(this->providers); + this->handlers->destroy(this->handlers); + this->lock->destroy(this->lock); + free(this); +} + +/* + * see header file + */ +attribute_manager_t *attribute_manager_create() +{ + private_attribute_manager_t *this; + + INIT(this, + .public = { + .acquire_address = _acquire_address, + .release_address = _release_address, + .create_responder_enumerator = _create_responder_enumerator, + .add_provider = _add_provider, + .remove_provider = _remove_provider, + .handle = _handle, + .release = _release, + .create_initiator_enumerator = _create_initiator_enumerator, + .add_handler = _add_handler, + .remove_handler = _remove_handler, + .destroy = _destroy, + }, + .providers = linked_list_create(), + .handlers = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/attributes/attribute_manager.h b/src/libcharon/attributes/attribute_manager.h new file mode 100644 index 000000000..6db664968 --- /dev/null +++ b/src/libcharon/attributes/attribute_manager.h @@ -0,0 +1,154 @@ +/* + * 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 attribute_manager attribute_manager + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_MANAGER_H_ +#define ATTRIBUTE_MANAGER_H_ + +#include "attribute_provider.h" +#include "attribute_handler.h" + +#include <sa/ike_sa.h> + +typedef struct attribute_manager_t attribute_manager_t; + +/** + * The attribute manager hands out attributes or handles them. + * + * The attribute manager manages both, attribute providers and attribute + * handlers. Attribute providers are responsible to hand out attributes if + * a connecting peer requests them. Handlers handle such attributes if they + * are received on the requesting peer. + */ +struct attribute_manager_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pools list of pool names (char*) to acquire from + * @param ike_sa associated IKE_SA for which an address is requested + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_manager_t *this, + linked_list_t *pool, ike_sa_t *ike_sa, + host_t *requested); + + /** + * Release a previously acquired address. + * + * @param pools list of pool names (char*) to release to + * @param address address to release + * @param ike_sa associated IKE_SA for which an address is released + * @return TRUE if address released to pool + */ + bool (*release_address)(attribute_manager_t *this, + linked_list_t *pools, host_t *address, + ike_sa_t *ike_sa); + + /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param pool list of pools names (char*) to query attributes from + * @param ike_sa associated IKE_SA for which attributes are requested + * @param vip list of virtual IPs (host_t*) to assign to peer + * @return enumerator (configuration_attribute_type_t, chunk_t) + */ + enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this, + linked_list_t *pool, ike_sa_t *ike_sa, + linked_list_t *vips); + + /** + * Register an attribute provider to the manager. + * + * @param provider attribute provider to register + */ + void (*add_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + /** + * Unregister an attribute provider from the manager. + * + * @param provider attribute provider to unregister + */ + void (*remove_provider)(attribute_manager_t *this, + attribute_provider_t *provider); + + /** + * Handle a configuration attribute by passing them to the handlers. + * + * @param ike_sa associated IKE_SA to handle an attribute for + * @param handler handler we requested the attribute for, if any + * @param type type of configuration attribute + * @param data associated attribute data + * @return handler which handled this attribute, NULL if none + */ + attribute_handler_t* (*handle)(attribute_manager_t *this, + ike_sa_t *ike_sa, attribute_handler_t *handler, + configuration_attribute_type_t type, chunk_t data); + + /** + * Release an attribute previously handle()d by a handler. + * + * @param ike_sa associated IKE_SA to release an attribute for + * @param server server from which the attribute was received + * @param type type of attribute to release + * @param data associated attribute data + */ + void (*release)(attribute_manager_t *this, attribute_handler_t *handler, + ike_sa_t *ike_sa, configuration_attribute_type_t type, + chunk_t data); + + /** + * Create an enumerator over attributes to request from server. + * + * @param ike_sa associated IKE_SA to request attributes for + * @param vip list of virtual IPs (host_t*) going to request + * @return enumerator (attribute_handler_t, ca_type_t, chunk_t) + */ + enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this, + ike_sa_t *ike_sa, linked_list_t *vips); + + /** + * Register an attribute handler to the manager. + * + * @param handler attribute handler to register + */ + void (*add_handler)(attribute_manager_t *this, + attribute_handler_t *handler); + + /** + * Unregister an attribute handler from the manager. + * + * @param handler attribute handler to unregister + */ + void (*remove_handler)(attribute_manager_t *this, + attribute_handler_t *handler); + + /** + * Destroy a attribute_manager instance. + */ + void (*destroy)(attribute_manager_t *this); +}; + +/** + * Create a attribute_manager instance. + */ +attribute_manager_t *attribute_manager_create(); + +#endif /** ATTRIBUTE_MANAGER_H_ @}*/ diff --git a/src/libcharon/attributes/attribute_provider.h b/src/libcharon/attributes/attribute_provider.h new file mode 100644 index 000000000..57453c2a0 --- /dev/null +++ b/src/libcharon/attributes/attribute_provider.h @@ -0,0 +1,71 @@ +/* + * 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 attribute_provider attribute_provider + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTE_PROVIDER_H_ +#define ATTRIBUTE_PROVIDER_H_ + +#include <sa/ike_sa.h> +#include <networking/host.h> +#include <collections/linked_list.h> + +typedef struct attribute_provider_t attribute_provider_t; + +/** + * Interface to provide attributes to peers through attribute manager. + */ +struct attribute_provider_t { + + /** + * Acquire a virtual IP address to assign to a peer. + * + * @param pools list of pool names (char*) to acquire from + * @param ike_sa associated IKE_SA to assign address over + * @param requested IP in configuration request + * @return allocated address, NULL to serve none + */ + host_t* (*acquire_address)(attribute_provider_t *this, + linked_list_t *pools, ike_sa_t *ike_sa, + host_t *requested); + /** + * Release a previously acquired address. + * + * @param pools list of pool names (char*) to release to + * @param address address to release + * @param ike_sa IKE_SA to release address for + * @return TRUE if the address has been released by the provider + */ + bool (*release_address)(attribute_provider_t *this, + linked_list_t *pools, host_t *address, + ike_sa_t *ike_sa); + + /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param pool list of pools names (char*) to query attributes from + * @param ike_sa IKE_SA to request attributes for + * @param vip list of virtual IPs (host_t*) to assign to peer + * @return enumerator (configuration_attribute_type_t, chunk_t) + */ + enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this, + linked_list_t *pools, ike_sa_t *ike_sa, + linked_list_t *vips); +}; + +#endif /** ATTRIBUTE_PROVIDER_H_ @}*/ diff --git a/src/libcharon/attributes/attributes.c b/src/libcharon/attributes/attributes.c new file mode 100644 index 000000000..9fabcf4e4 --- /dev/null +++ b/src/libcharon/attributes/attributes.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * 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 "attributes.h" + +ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, + "INTERNAL_IP4_ADDRESS", + "INTERNAL_IP4_NETMASK", + "INTERNAL_IP4_DNS", + "INTERNAL_IP4_NBNS", + "INTERNAL_ADDRESS_EXPIRY", + "INTERNAL_IP4_DHCP", + "APPLICATION_VERSION", + "INTERNAL_IP6_ADDRESS", + "INTERNAL_IP6_NETMASK", + "INTERNAL_IP6_DNS", + "INTERNAL_IP6_NBNS", + "INTERNAL_IP6_DHCP", + "INTERNAL_IP4_SUBNET", + "SUPPORTED_ATTRIBUTES", + "INTERNAL_IP6_SUBNET", + "MIP6_HOME_PREFIX", + "INTERNAL_IP6_LINK", + "INTERNAL_IP6_PREFIX", + "HOME_AGENT_ADDRESS"); +ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS, + "XAUTH_TYPE", + "XAUTH_USER_NAME", + "XAUTH_USER_PASSWORD", + "XAUTH_PASSCODE", + "XAUTH_MESSAGE", + "XAUTH_CHALLENGE", + "XAUTH_DOMAIN", + "XAUTH_STATUS", + "XAUTH_NEXT_PIN", + "XAUTH_ANSWER"); +ENUM_NEXT(configuration_attribute_type_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER, + "INTERNAL_IP4_SERVER", + "INTERNAL_IP6_SERVER"); +ENUM_NEXT(configuration_attribute_type_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER, + "UNITY_BANNER", + "UNITY_SAVE_PASSWD", + "UNITY_DEF_DOMAIN", + "UNITY_SPLITDNS_NAME", + "UNITY_SPLIT_INCLUDE", + "UNITY_NATT_PORT", + "UNITY_LOCAL_LAN", + "UNITY_PFS", + "UNITY_FW_TYPE", + "UNITY_BACKUP_SERVERS", + "UNITY_DDNS_HOSTNAME"); +ENUM_END(configuration_attribute_type_names, UNITY_DDNS_HOSTNAME); + +ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS, + "ADDR", + "MASK", + "DNS", + "NBNS", + "EXP", + "DHCP", + "VER", + "ADDR6", + "MASK6", + "DNS6", + "NBNS6", + "DHCP6", + "SUBNET", + "SUP", + "SUBNET6", + "MIP6HPFX", + "LINK6", + "PFX6", + "HOA"); +ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS, + "X_TYPE", + "X_USER", + "X_PWD", + "X_CODE", + "X_MSG", + "X_CHALL", + "X_DOMAIN", + "X_STATUS", + "X_PIN", + "X_ANSWER"); +ENUM_NEXT(configuration_attribute_type_short_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER, + "SRV", + "SRV6"); +ENUM_NEXT(configuration_attribute_type_short_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER, + "U_BANNER", + "U_SAVEPWD", + "U_DEFDOM", + "U_SPLITDNS", + "U_SPLITINC", + "U_NATTPORT", + "U_LOCALLAN", + "U_PFS", + "U_FWTYPE", + "U_BKPSRV", + "U_DDNSHOST"); +ENUM_END(configuration_attribute_type_short_names, UNITY_DDNS_HOSTNAME); diff --git a/src/libcharon/attributes/attributes.h b/src/libcharon/attributes/attributes.h new file mode 100644 index 000000000..5d1e9f9ba --- /dev/null +++ b/src/libcharon/attributes/attributes.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * 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 attributes_g attributes + * @{ @ingroup attributes + */ + +#ifndef ATTRIBUTES_H_ +#define ATTRIBUTES_H_ + +typedef enum configuration_attribute_type_t configuration_attribute_type_t; + +#include <utils/utils.h> + +/** + * Type of the attribute, as in IKEv2 RFC 3.15.1 or IKEv1 ModeConfig. + */ +enum configuration_attribute_type_t { + INTERNAL_IP4_ADDRESS = 1, + INTERNAL_IP4_NETMASK = 2, + INTERNAL_IP4_DNS = 3, + INTERNAL_IP4_NBNS = 4, + INTERNAL_ADDRESS_EXPIRY = 5, + INTERNAL_IP4_DHCP = 6, + APPLICATION_VERSION = 7, + INTERNAL_IP6_ADDRESS = 8, + INTERNAL_IP6_NETMASK = 9, + INTERNAL_IP6_DNS = 10, + INTERNAL_IP6_NBNS = 11, + INTERNAL_IP6_DHCP = 12, + INTERNAL_IP4_SUBNET = 13, + SUPPORTED_ATTRIBUTES = 14, + INTERNAL_IP6_SUBNET = 15, + MIP6_HOME_PREFIX = 16, + INTERNAL_IP6_LINK = 17, + INTERNAL_IP6_PREFIX = 18, + HOME_AGENT_ADDRESS = 19, + /* XAUTH attributes */ + XAUTH_TYPE = 16520, + XAUTH_USER_NAME = 16521, + XAUTH_USER_PASSWORD = 16522, + XAUTH_PASSCODE = 16523, + XAUTH_MESSAGE = 16524, + XAUTH_CHALLENGE = 16525, + XAUTH_DOMAIN = 16526, + XAUTH_STATUS = 16527, + XAUTH_NEXT_PIN = 16528, + XAUTH_ANSWER = 16529, + /* proprietary Microsoft attributes */ + INTERNAL_IP4_SERVER = 23456, + INTERNAL_IP6_SERVER = 23457, + /* proprietary Cisco Unity attributes */ + UNITY_BANNER = 28672, + UNITY_SAVE_PASSWD = 28673, + UNITY_DEF_DOMAIN = 28674, + UNITY_SPLITDNS_NAME = 28675, + UNITY_SPLIT_INCLUDE = 28676, + UNITY_NATT_PORT = 28677, + UNITY_LOCAL_LAN = 28678, + UNITY_PFS = 28679, + UNITY_FW_TYPE = 28680, + UNITY_BACKUP_SERVERS = 28681, + UNITY_DDNS_HOSTNAME = 28682 +}; + +/** + * enum names for configuration_attribute_type_t. + */ +extern enum_name_t *configuration_attribute_type_names; + +/** + * Short enum names for configuration_attribute_type_t. + */ +extern enum_name_t *configuration_attribute_type_short_names; + + +#endif /** ATTRIBUTES_H_ @}*/ diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c new file mode 100644 index 000000000..279668249 --- /dev/null +++ b/src/libcharon/attributes/mem_pool.c @@ -0,0 +1,735 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * Copyright (C) 2008-2010 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 "mem_pool.h" + +#include <library.h> +#include <hydra.h> +#include <utils/debug.h> +#include <collections/hashtable.h> +#include <collections/array.h> +#include <threading/mutex.h> + +#define POOL_LIMIT (sizeof(u_int)*8 - 1) + +typedef struct private_mem_pool_t private_mem_pool_t; + +/** + * private data of mem_pool_t + */ +struct private_mem_pool_t { + /** + * public interface + */ + mem_pool_t public; + + /** + * name of the pool + */ + char *name; + + /** + * base address of the pool + */ + host_t *base; + + /** + * whether base is the network id of the subnet on which the pool is based + */ + bool base_is_network_id; + + /** + * size of the pool + */ + u_int size; + + /** + * next unused address + */ + u_int unused; + + /** + * lease hashtable [identity => entry] + */ + hashtable_t *leases; + + /** + * lock to safely access the pool + */ + mutex_t *mutex; +}; + +/** + * A unique lease address offset, with a hash of the peer host address + */ +typedef struct { + /** lease, as offset */ + u_int offset; + /** hash of remote address, to allow duplicates */ + u_int hash; +} unique_lease_t; + +/** + * Lease entry. + */ +typedef struct { + /* identitiy reference */ + identification_t *id; + /* array of online leases, as unique_lease_t */ + array_t *online; + /* array of offline leases, as u_int offset */ + array_t *offline; +} entry_t; + +/** + * Create a new entry + */ +static entry_t* entry_create(identification_t *id) +{ + entry_t *entry; + + INIT(entry, + .id = id->clone(id), + .online = array_create(sizeof(unique_lease_t), 0), + .offline = array_create(sizeof(u_int), 0), + ); + return entry; +} + +/** + * Destroy an entry + */ +static void entry_destroy(entry_t *this) +{ + this->id->destroy(this->id); + array_destroy(this->online); + array_destroy(this->offline); + free(this); +} + +/** + * hashtable hash function for identities + */ +static u_int id_hash(identification_t *id) +{ + return chunk_hash(id->get_encoding(id)); +} + +/** + * hashtable equals function for identities + */ +static bool id_equals(identification_t *a, identification_t *b) +{ + return a->equals(a, b); +} + +/** + * convert a pool offset to an address + */ +static host_t* offset2host(private_mem_pool_t *pool, int offset) +{ + chunk_t addr; + host_t *host; + u_int32_t *pos; + + offset--; + 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(private_mem_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 + 1; +} + +METHOD(mem_pool_t, get_name, const char*, + private_mem_pool_t *this) +{ + return this->name; +} + +METHOD(mem_pool_t, get_base, host_t*, + private_mem_pool_t *this) +{ + return this->base; +} + +METHOD(mem_pool_t, get_size, u_int, + private_mem_pool_t *this) +{ + return this->size; +} + +METHOD(mem_pool_t, get_online, u_int, + private_mem_pool_t *this) +{ + enumerator_t *enumerator; + entry_t *entry; + u_int count = 0; + + this->mutex->lock(this->mutex); + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + count += array_count(entry->online); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + return count; +} + +METHOD(mem_pool_t, get_offline, u_int, + private_mem_pool_t *this) +{ + enumerator_t *enumerator; + entry_t *entry; + u_int count = 0; + + this->mutex->lock(this->mutex); + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + count += array_count(entry->offline); + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + return count; +} + +/** + * Create a unique hash for a remote address + */ +static u_int hash_addr(host_t *addr) +{ + if (addr) + { + return chunk_hash_inc(addr->get_address(addr), addr->get_port(addr)); + } + return 0; +} + +/** + * Get an existing lease for id + */ +static int get_existing(private_mem_pool_t *this, identification_t *id, + host_t *requested, host_t *peer) +{ + enumerator_t *enumerator; + unique_lease_t *lease, reassign; + u_int *current; + entry_t *entry; + int offset = 0; + + entry = this->leases->get(this->leases, id); + if (!entry) + { + return 0; + } + + /* check for a valid offline lease, refresh */ + enumerator = array_create_enumerator(entry->offline); + if (enumerator->enumerate(enumerator, ¤t)) + { + reassign.offset = offset = *current; + reassign.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &reassign); + array_remove_at(entry->offline, enumerator); + } + enumerator->destroy(enumerator); + if (offset) + { + DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id); + return offset; + } + if (!peer) + { + return 0; + } + /* check for a valid online lease to reassign */ + enumerator = array_create_enumerator(entry->online); + while (enumerator->enumerate(enumerator, &lease)) + { + if (lease->offset == host2offset(this, requested) && + lease->hash == hash_addr(peer)) + { + offset = lease->offset; + /* add an additional "online" entry */ + array_insert(entry->online, ARRAY_TAIL, lease); + break; + } + } + enumerator->destroy(enumerator); + if (offset) + { + DBG1(DBG_CFG, "reassigning online lease to '%Y'", id); + } + return offset; +} + +/** + * Get a new lease for id + */ +static int get_new(private_mem_pool_t *this, identification_t *id, host_t *peer) +{ + entry_t *entry; + unique_lease_t lease = {}; + + if (this->unused < this->size) + { + entry = this->leases->get(this->leases, id); + if (!entry) + { + entry = entry_create(id); + this->leases->put(this->leases, entry->id, entry); + } + /* assigning offset, starting by 1 */ + lease.offset = ++this->unused + (this->base_is_network_id ? 1 : 0); + lease.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &lease); + DBG1(DBG_CFG, "assigning new lease to '%Y'", id); + } + return lease.offset; +} + +/** + * Get a reassigned lease for id in case the pool is full + */ +static int get_reassigned(private_mem_pool_t *this, identification_t *id, + host_t *peer) +{ + enumerator_t *enumerator; + entry_t *entry; + u_int current; + unique_lease_t lease = {}; + + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + if (array_remove(entry->offline, ARRAY_HEAD, ¤t)) + { + lease.offset = current; + DBG1(DBG_CFG, "reassigning existing offline lease by '%Y' " + "to '%Y'", entry->id, id); + } + if (!array_count(entry->online) && !array_count(entry->offline)) + { + this->leases->remove_at(this->leases, enumerator); + entry_destroy(entry); + } + if (lease.offset) + { + break; + } + } + enumerator->destroy(enumerator); + + if (lease.offset) + { + entry = this->leases->get(this->leases, id); + if (!entry) + { + entry = entry_create(id); + this->leases->put(this->leases, entry->id, entry); + } + lease.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &lease); + } + return lease.offset; +} + +METHOD(mem_pool_t, acquire_address, host_t*, + private_mem_pool_t *this, identification_t *id, host_t *requested, + mem_pool_op_t operation, host_t *peer) +{ + int offset = 0; + + /* if the pool is empty (e.g. in the %config case) we simply return the + * requested address */ + if (this->size == 0) + { + return requested->clone(requested); + } + + if (requested->get_family(requested) != + this->base->get_family(this->base)) + { + return NULL; + } + + this->mutex->lock(this->mutex); + switch (operation) + { + case MEM_POOL_EXISTING: + offset = get_existing(this, id, requested, peer); + break; + case MEM_POOL_NEW: + offset = get_new(this, id, peer); + break; + case MEM_POOL_REASSIGN: + offset = get_reassigned(this, id, peer); + if (!offset) + { + DBG1(DBG_CFG, "pool '%s' is full, unable to assign address", + this->name); + } + break; + default: + break; + } + this->mutex->unlock(this->mutex); + + if (offset) + { + return offset2host(this, offset); + } + return NULL; +} + +METHOD(mem_pool_t, release_address, bool, + private_mem_pool_t *this, host_t *address, identification_t *id) +{ + enumerator_t *enumerator; + bool found = FALSE, more = FALSE; + entry_t *entry; + u_int offset; + unique_lease_t *current; + + if (this->size != 0) + { + this->mutex->lock(this->mutex); + entry = this->leases->get(this->leases, id); + if (entry) + { + offset = host2offset(this, address); + + enumerator = array_create_enumerator(entry->online); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (current->offset == offset) + { + if (!found) + { /* remove the first entry only */ + array_remove_at(entry->online, enumerator); + found = TRUE; + } + else + { /* but check for more entries */ + more = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + + if (found && !more) + { + /* no tunnels are online anymore for this lease, make offline */ + array_insert(entry->offline, ARRAY_TAIL, &offset); + DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id); + } + } + this->mutex->unlock(this->mutex); + } + return found; +} + +/** + * lease enumerator + */ +typedef struct { + /** implemented enumerator interface */ + enumerator_t public; + /** hash-table enumerator */ + enumerator_t *entries; + /** online enumerator */ + enumerator_t *online; + /** offline enumerator */ + enumerator_t *offline; + /** enumerated pool */ + private_mem_pool_t *pool; + /** currently enumerated entry */ + entry_t *entry; + /** currently enumerated lease address */ + host_t *addr; +} lease_enumerator_t; + +METHOD(enumerator_t, lease_enumerate, bool, + lease_enumerator_t *this, identification_t **id, host_t **addr, bool *online) +{ + u_int *offset; + unique_lease_t *lease; + + DESTROY_IF(this->addr); + this->addr = NULL; + + while (TRUE) + { + if (this->entry) + { + if (this->online->enumerate(this->online, &lease)) + { + *id = this->entry->id; + *addr = this->addr = offset2host(this->pool, lease->offset); + *online = TRUE; + return TRUE; + } + if (this->offline->enumerate(this->offline, &offset)) + { + *id = this->entry->id; + *addr = this->addr = offset2host(this->pool, *offset); + *online = FALSE; + return TRUE; + } + this->online->destroy(this->online); + this->offline->destroy(this->offline); + this->online = this->offline = NULL; + } + if (!this->entries->enumerate(this->entries, NULL, &this->entry)) + { + return FALSE; + } + this->online = array_create_enumerator(this->entry->online); + this->offline = array_create_enumerator(this->entry->offline); + } +} + +METHOD(enumerator_t, lease_enumerator_destroy, void, + lease_enumerator_t *this) +{ + DESTROY_IF(this->addr); + DESTROY_IF(this->online); + DESTROY_IF(this->offline); + this->entries->destroy(this->entries); + this->pool->mutex->unlock(this->pool->mutex); + free(this); +} + +METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*, + private_mem_pool_t *this) +{ + lease_enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + INIT(enumerator, + .public = { + .enumerate = (void*)_lease_enumerate, + .destroy = _lease_enumerator_destroy, + }, + .pool = this, + .entries = this->leases->create_enumerator(this->leases), + ); + return &enumerator->public; +} + +METHOD(mem_pool_t, destroy, void, + private_mem_pool_t *this) +{ + enumerator_t *enumerator; + entry_t *entry; + + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + entry_destroy(entry); + } + enumerator->destroy(enumerator); + + this->leases->destroy(this->leases); + this->mutex->destroy(this->mutex); + DESTROY_IF(this->base); + free(this->name); + free(this); +} + +/** + * Generic constructor + */ +static private_mem_pool_t *create_generic(char *name) +{ + private_mem_pool_t *this; + + INIT(this, + .public = { + .get_name = _get_name, + .get_base = _get_base, + .get_size = _get_size, + .get_online = _get_online, + .get_offline = _get_offline, + .acquire_address = _acquire_address, + .release_address = _release_address, + .create_lease_enumerator = _create_lease_enumerator, + .destroy = _destroy, + }, + .name = strdup(name), + .leases = hashtable_create((hashtable_hash_t)id_hash, + (hashtable_equals_t)id_equals, 16), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return this; +} + +/** + * Check if the given host is the network ID of a subnet, that is, if hostbits + * are zero. Since we limit pools to 2^31 addresses we only have to check the + * last 4 bytes. + */ +static u_int network_id_diff(host_t *host, int hostbits) +{ + u_int32_t last; + chunk_t addr; + + if (!hostbits) + { + return 0; + } + addr = host->get_address(host); + last = untoh32(addr.ptr + addr.len - sizeof(last)); + hostbits = sizeof(last) * 8 - hostbits; + return (last << hostbits) >> hostbits; +} + +/** + * Described in header + */ +mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) +{ + private_mem_pool_t *this; + u_int diff; + int addr_bits; + + this = create_generic(name); + if (base) + { + addr_bits = base->get_family(base) == AF_INET ? 32 : 128; + bits = max(0, min(bits, addr_bits)); + /* net bits -> host bits */ + bits = addr_bits - bits; + if (bits > POOL_LIMIT) + { + bits = POOL_LIMIT; + DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d", + base, addr_bits - bits); + } + this->size = 1 << bits; + this->base = base->clone(base); + + if (this->size > 2) + { + /* if base is the network id we later skip the first address, + * otherwise adjust the size to represent the actual number + * of assignable addresses */ + diff = network_id_diff(base, bits); + if (!diff) + { + this->base_is_network_id = TRUE; + this->size--; + } + else + { + this->size -= diff; + } + /* skip the last address (broadcast) of the subnet */ + this->size--; + } + else if (network_id_diff(base, bits)) + { /* only serve the second address of the subnet */ + this->size--; + } + } + return &this->public; +} + +/** + * Described in header + */ +mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to) +{ + private_mem_pool_t *this; + chunk_t fromaddr, toaddr; + u_int32_t diff; + + fromaddr = from->get_address(from); + toaddr = to->get_address(to); + + if (from->get_family(from) != to->get_family(to) || + fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) || + memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0) + { + DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to); + return NULL; + } + if (fromaddr.len > sizeof(diff) && + !chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)), + chunk_create(toaddr.ptr, toaddr.len - sizeof(diff)))) + { + DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to); + return NULL; + } + this = create_generic(name); + this->base = from->clone(from); + diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) - + untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff)); + this->size = diff + 1; + + return &this->public; +} diff --git a/src/libcharon/attributes/mem_pool.h b/src/libcharon/attributes/mem_pool.h new file mode 100644 index 000000000..3ee1dd37d --- /dev/null +++ b/src/libcharon/attributes/mem_pool.h @@ -0,0 +1,154 @@ +/* + * 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 mem_pool mem_pool + * @{ @ingroup attributes + */ + +#ifndef MEM_POOL_H +#define MEM_POOL_H + +typedef struct mem_pool_t mem_pool_t; +typedef enum mem_pool_op_t mem_pool_op_t; + +#include <networking/host.h> +#include <utils/identification.h> + +/** + * In-memory IP pool acquire operation. + */ +enum mem_pool_op_t { + /** Check for an exsiting lease */ + MEM_POOL_EXISTING, + /** Get a new lease */ + MEM_POOL_NEW, + /** Replace an existing offline lease of another ID */ + MEM_POOL_REASSIGN, +}; + +/** + * An in-memory IP address pool. + */ +struct mem_pool_t { + + /** + * Get the name of this pool. + * + * @return the name of this pool + */ + const char* (*get_name)(mem_pool_t *this); + + /** + * Get the base (first) address of this pool. + * + * @return base address, internal host + */ + host_t* (*get_base)(mem_pool_t *this); + + /** + * Get the size (i.e. number of addresses) of this pool. + * + * @return the size of this pool + */ + u_int (*get_size)(mem_pool_t *this); + + /** + * Get the number of online leases. + * + * @return the number of offline leases + */ + u_int (*get_online)(mem_pool_t *this); + + /** + * Get the number of offline leases. + * + * @return the number of online leases + */ + u_int (*get_offline)(mem_pool_t *this); + + /** + * Acquire an address for the given id from this pool. + * + * This call is usually invoked several times: The first time to find an + * existing lease (MEM_POOL_EXISTING), if none found a second time to + * acquire a new lease (MEM_POOL_NEW), and if the pool is full once again + * to assign an existing offline lease (MEM_POOL_REASSIGN). + * + * If the same identity requests a virtual IP that is already assigned to + * it, the peer address and port is used to check if it is the same client + * instance that is connecting. If this is true, the request is considered + * a request for a reauthentication attempt, and the same virtual IP gets + * assigned to the peer. + * + * @param id the id to acquire an address for + * @param requested acquire this address, if possible + * @param operation acquire operation to perform, see above + * @param peer optional remote IKE address and port + * @return the acquired address + */ + host_t* (*acquire_address)(mem_pool_t *this, identification_t *id, + host_t *requested, mem_pool_op_t operation, + host_t *peer); + + /** + * Release a previously acquired address. + * + * @param address the address to release + * @param id the id the address was assigned to + * @return TRUE, if the lease was found + */ + bool (*release_address)(mem_pool_t *this, host_t *address, + identification_t *id); + + /** + * Create an enumerator over the leases of this pool. + * + * Enumerator enumerates over + * identification_t *id, host_t *address, bool online + * + * @return enumerator + */ + enumerator_t* (*create_lease_enumerator)(mem_pool_t *this); + + /** + * Destroy a mem_pool_t instance. + */ + void (*destroy)(mem_pool_t *this); +}; + +/** + * Create an in-memory IP address pool. + * + * An empty pool just returns the requested address. + * + * @param name name of this pool + * @param base base address of this pool, NULL to create an empty pool + * @param bits number of non-network bits in base, as in CIDR notation + * @return memory pool instance + */ +mem_pool_t *mem_pool_create(char *name, host_t *base, int bits); + +/** + * Create an in-memory IP address from a range. + * + * @param name name of this pool + * @param from start of ranged pool + * @param to end of ranged pool + * @return memory pool instance, NULL if range invalid + */ +mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to); + +#endif /** MEM_POOL_H_ @} */ diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c index cb59f976b..7938f46cc 100644 --- a/src/libcharon/bus/bus.c +++ b/src/libcharon/bus/bus.c @@ -755,6 +755,33 @@ METHOD(bus_t, ike_rekey, void, this->mutex->unlock(this->mutex); } +METHOD(bus_t, ike_update, void, + private_bus_t *this, ike_sa_t *ike_sa, bool local, host_t *new) +{ + enumerator_t *enumerator; + entry_t *entry; + bool keep; + + this->mutex->lock(this->mutex); + enumerator = this->listeners->create_enumerator(this->listeners); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->calling || !entry->listener->ike_update) + { + continue; + } + entry->calling++; + keep = entry->listener->ike_update(entry->listener, ike_sa, local, new); + entry->calling--; + if (!keep) + { + unregister_listener(this, entry, enumerator); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + METHOD(bus_t, ike_reestablish_pre, void, private_bus_t *this, ike_sa_t *old, ike_sa_t *new) { @@ -1006,6 +1033,7 @@ bus_t *bus_create() .child_keys = _child_keys, .ike_updown = _ike_updown, .ike_rekey = _ike_rekey, + .ike_update = _ike_update, .ike_reestablish_pre = _ike_reestablish_pre, .ike_reestablish_post = _ike_reestablish_post, .child_updown = _child_updown, diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h index e1d221ca5..051c429f9 100644 --- a/src/libcharon/bus/bus.h +++ b/src/libcharon/bus/bus.h @@ -382,6 +382,15 @@ struct bus_t { void (*ike_rekey)(bus_t *this, ike_sa_t *old, ike_sa_t *new); /** + * IKE_SA peer endpoint update hook. + * + * @param ike_sa updated IKE_SA, having old endpoints set + * @param local TRUE if local endpoint gets updated, FALSE for remote + * @param new new endpoint address and port + */ + void (*ike_update)(bus_t *this, ike_sa_t *ike_sa, bool local, host_t *new); + + /** * IKE_SA reestablishing hook (before resolving hosts). * * @param old reestablished and obsolete IKE_SA diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h index 0910cb361..3447d8f99 100644 --- a/src/libcharon/bus/listeners/listener.h +++ b/src/libcharon/bus/listeners/listener.h @@ -128,6 +128,17 @@ struct listener_t { bool (*ike_rekey)(listener_t *this, ike_sa_t *old, ike_sa_t *new); /** + * Hook called for IKE_SA peer endpoint updates. + * + * @param ike_sa updated IKE_SA, having old endpoints set + * @param local TRUE if local endpoint gets updated, FALSE for remote + * @param new new endpoint address and port + * @return TRUE to stay registered, FALSE to unregister + */ + bool (*ike_update)(listener_t *this, ike_sa_t *ike_sa, + bool local, host_t *new); + + /** * Hook called when an initiator reestablishes an IKE_SA. * * This is invoked right after creating the new IKE_SA and setting the diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index 42a3e9057..9464ceb5d 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -459,25 +459,10 @@ static traffic_selector_t* make_range(char *str) { traffic_selector_t *ts; ts_type_t type; - char *pos; host_t *from, *to; - pos = strchr(str, '-'); - if (!pos) - { - return NULL; - } - to = host_create_from_string(pos + 1, 0); - if (!to) - { - return NULL; - } - str = strndup(str, pos - str); - from = host_create_from_string_and_family(str, to->get_family(to), 0); - free(str); - if (!from) + if (!host_create_from_range(str, &from, &to)) { - to->destroy(to); return NULL; } if (to->get_family(to) == AF_INET) diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 50d3c6f66..e59dcd9ec 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -399,10 +399,12 @@ static const struct { pseudo_random_function_t prf; } integ_prf_map[] = { {AUTH_HMAC_SHA1_96, PRF_HMAC_SHA1 }, + {AUTH_HMAC_SHA1_160, PRF_HMAC_SHA1 }, {AUTH_HMAC_SHA2_256_128, PRF_HMAC_SHA2_256 }, {AUTH_HMAC_SHA2_384_192, PRF_HMAC_SHA2_384 }, {AUTH_HMAC_SHA2_512_256, PRF_HMAC_SHA2_512 }, {AUTH_HMAC_MD5_96, PRF_HMAC_MD5 }, + {AUTH_HMAC_MD5_128, PRF_HMAC_MD5 }, {AUTH_AES_XCBC_96, PRF_AES128_XCBC }, {AUTH_CAMELLIA_XCBC_96, PRF_CAMELLIA128_XCBC }, {AUTH_AES_CMAC_96, PRF_AES128_CMAC }, diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 25667e532..fd8349e2f 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -303,6 +303,18 @@ METHOD(listener_t, child_state_change, bool, /* proper delete */ this->status = SUCCESS; break; + case CHILD_RETRYING: + /* retrying with a different DH group; survive another + * initiation round */ + this->status = NEED_MORE; + return TRUE; + case CHILD_CREATED: + if (this->status == NEED_MORE) + { + this->status = FAILED; + return TRUE; + } + break; default: break; } @@ -437,7 +449,7 @@ METHOD(job_t, terminate_ike_execute, job_requeue_t, ike_sa_t *ike_sa; ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - unique_id, FALSE); + unique_id); if (!ike_sa) { DBG1(DBG_IKE, "unable to terminate IKE_SA: ID %d not found", unique_id); @@ -522,17 +534,15 @@ METHOD(job_t, terminate_child_execute, job_requeue_t, interface_job_t *job) { interface_listener_t *listener = &job->listener; - u_int32_t reqid = listener->id; - enumerator_t *enumerator; + u_int32_t id = listener->id; child_sa_t *child_sa; ike_sa_t *ike_sa; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - reqid, TRUE); + ike_sa = charon->child_sa_manager->checkout_by_id(charon->child_sa_manager, + id, &child_sa); if (!ike_sa) { - DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found", - reqid); + DBG1(DBG_IKE, "unable to terminate, CHILD_SA with ID %d not found", id); listener->status = NOT_FOUND; /* release listener */ listener_done(listener); @@ -542,22 +552,10 @@ METHOD(job_t, terminate_child_execute, job_requeue_t, listener->ike_sa = ike_sa; listener->lock->unlock(listener->lock); - enumerator = ike_sa->create_child_sa_enumerator(ike_sa); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) - { - if (child_sa->get_state(child_sa) != CHILD_ROUTED && - child_sa->get_reqid(child_sa) == reqid) - { - break; - } - child_sa = NULL; - } - enumerator->destroy(enumerator); - - if (!child_sa) + if (child_sa->get_state(child_sa) == CHILD_ROUTED) { DBG1(DBG_IKE, "unable to terminate, established " - "CHILD_SA with ID %d not found", reqid); + "CHILD_SA with ID %d not found", id); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); listener->status = NOT_FOUND; /* release listener */ @@ -584,7 +582,7 @@ METHOD(job_t, terminate_child_execute, job_requeue_t, } METHOD(controller_t, terminate_child, status_t, - controller_t *this, u_int32_t reqid, + controller_t *this, u_int32_t unique_id, controller_cb_t callback, void *param, u_int timeout) { interface_job_t *job; @@ -605,7 +603,7 @@ METHOD(controller_t, terminate_child, status_t, .param = param, }, .status = FAILED, - .id = reqid, + .id = unique_id, .lock = spinlock_create(), }, .public = { diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h index 222285cde..02f4ebb2b 100644 --- a/src/libcharon/control/controller.h +++ b/src/libcharon/control/controller.h @@ -118,7 +118,7 @@ struct controller_t { * If a callback is provided the function is synchronous and thus blocks * until the CHILD_SA is properly deleted, or the call timed out. * - * @param reqid reqid of the CHILD_SA to terminate + * @param unique_id CHILD_SA unique ID to terminate * @param cb logging callback * @param param parameter to include in each call of cb * @param timeout timeout in ms to wait for callbacks, 0 to disable @@ -128,7 +128,7 @@ struct controller_t { * - NEED_MORE, if callback returned FALSE * - OUT_OF_RES if timed out */ - status_t (*terminate_child)(controller_t *this, u_int32_t reqid, + status_t (*terminate_child)(controller_t *this, u_int32_t unique_id, controller_cb_t callback, void *param, u_int timeout); diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index 3ae7c4e6f..b1b8f57f0 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -474,12 +474,15 @@ static void destroy(private_daemon_t *this) DESTROY_IF(this->public.connect_manager); DESTROY_IF(this->public.mediation_manager); #endif /* ME */ - /* make sure the cache is clear before unloading plugins */ + /* make sure the cache and scheduler are clear before unloading plugins */ lib->credmgr->flush_cache(lib->credmgr, CERT_ANY); + lib->scheduler->flush(lib->scheduler); lib->plugins->unload(lib->plugins); + DESTROY_IF(this->public.attributes); DESTROY_IF(this->kernel_handler); DESTROY_IF(this->public.traps); DESTROY_IF(this->public.shunts); + DESTROY_IF(this->public.child_sa_manager); DESTROY_IF(this->public.ike_sa_manager); DESTROY_IF(this->public.controller); DESTROY_IF(this->public.eap); @@ -606,6 +609,7 @@ METHOD(daemon_t, initialize, bool, { return FALSE; } + this->public.child_sa_manager = child_sa_manager_create(); /* Queue start_action job */ lib->processor->queue_job(lib->processor, (job_t*)start_action_job_create()); @@ -642,6 +646,7 @@ private_daemon_t *daemon_create() .ref = 1, ); charon = &this->public; + this->public.attributes = attribute_manager_create(); this->public.controller = controller_create(); this->public.eap = eap_manager_create(); this->public.xauth = xauth_manager_create(); diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h index 36242bb04..d16bf1ddb 100644 --- a/src/libcharon/daemon.h +++ b/src/libcharon/daemon.h @@ -19,6 +19,9 @@ /** * @defgroup libcharon libcharon * + * @defgroup attributes attributes + * @ingroup libcharon + * * @defgroup bus bus * @ingroup libcharon * @@ -152,12 +155,14 @@ typedef struct daemon_t daemon_t; +#include <attributes/attribute_manager.h> #include <network/sender.h> #include <network/receiver.h> #include <network/socket_manager.h> #include <control/controller.h> #include <bus/bus.h> #include <sa/ike_sa_manager.h> +#include <sa/child_sa_manager.h> #include <sa/trap_manager.h> #include <sa/shunt_manager.h> #include <config/backend_manager.h> @@ -215,6 +220,11 @@ struct daemon_t { ike_sa_manager_t *ike_sa_manager; /** + * A child_sa_manager_t instance. + */ + child_sa_manager_t *child_sa_manager; + + /** * Manager for triggering policies, called traps */ trap_manager_t *traps; @@ -240,6 +250,11 @@ struct daemon_t { receiver_t *receiver; /** + * Manager for IKE configuration attributes + */ + attribute_manager_t *attributes; + + /** * The signaling bus. */ bus_t *bus; diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index cb6c97f25..0a596ffb0 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -180,6 +180,7 @@ static payload_order_t ike_sa_init_r_order[] = { */ static payload_rule_t ike_auth_i_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {PLV2_EAP, 0, 1, TRUE, TRUE}, {PLV2_AUTH, 0, 1, TRUE, TRUE}, @@ -227,6 +228,7 @@ static payload_order_t ike_auth_i_order[] = { {PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES}, {PLV2_NOTIFY, 0}, {PLV2_VENDOR_ID, 0}, + {PLV2_FRAGMENT, 0}, }; /** @@ -234,6 +236,7 @@ static payload_order_t ike_auth_i_order[] = { */ static payload_rule_t ike_auth_r_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, {PLV2_EAP, 0, 1, TRUE, TRUE}, {PLV2_AUTH, 0, 1, TRUE, TRUE}, @@ -270,6 +273,7 @@ static payload_order_t ike_auth_r_order[] = { {PLV2_NOTIFY, NO_ADDITIONAL_ADDRESSES}, {PLV2_NOTIFY, 0}, {PLV2_VENDOR_ID, 0}, + {PLV2_FRAGMENT, 0}, }; /** @@ -277,6 +281,7 @@ static payload_order_t ike_auth_r_order[] = { */ static payload_rule_t informational_i_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE}, {PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, @@ -295,6 +300,7 @@ static payload_order_t informational_i_order[] = { {PLV2_NOTIFY, 0}, {PLV2_DELETE, 0}, {PLV2_CONFIGURATION, 0}, + {PLV2_FRAGMENT, 0}, }; /** @@ -302,6 +308,7 @@ static payload_order_t informational_i_order[] = { */ static payload_rule_t informational_r_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {PLV2_CONFIGURATION, 0, 1, TRUE, FALSE}, {PLV2_DELETE, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, @@ -320,6 +327,7 @@ static payload_order_t informational_r_order[] = { {PLV2_NOTIFY, 0}, {PLV2_DELETE, 0}, {PLV2_CONFIGURATION, 0}, + {PLV2_FRAGMENT, 0}, }; /** @@ -327,6 +335,7 @@ static payload_order_t informational_r_order[] = { */ static payload_rule_t create_child_sa_i_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE}, {PLV2_NONCE, 1, 1, TRUE, FALSE}, @@ -353,6 +362,7 @@ static payload_order_t create_child_sa_i_order[] = { {PLV2_TS_INITIATOR, 0}, {PLV2_TS_RESPONDER, 0}, {PLV2_NOTIFY, 0}, + {PLV2_FRAGMENT, 0}, }; /** @@ -360,6 +370,7 @@ static payload_order_t create_child_sa_i_order[] = { */ static payload_rule_t create_child_sa_r_rules[] = { /* payload type min max encr suff */ + {PLV2_FRAGMENT, 0, 1, TRUE, TRUE}, {PLV2_NOTIFY, 0, MAX_NOTIFY_PAYLOADS, TRUE, TRUE}, {PLV2_SECURITY_ASSOCIATION, 1, 1, TRUE, FALSE}, {PLV2_NONCE, 1, 1, TRUE, FALSE}, @@ -386,6 +397,7 @@ static payload_order_t create_child_sa_r_order[] = { {PLV2_TS_RESPONDER, 0}, {PLV2_NOTIFY, ADDITIONAL_TS_POSSIBLE}, {PLV2_NOTIFY, 0}, + {PLV2_FRAGMENT, 0}, }; #ifdef ME @@ -2143,6 +2155,8 @@ METHOD(message_t, parse_header, status_t, } ike_header->destroy(ike_header); + this->parser->set_major_version(this->parser, this->major_version); + DBG2(DBG_ENC, "parsed a %N %s header", exchange_type_names, this->exchange_type, this->major_version == IKEV1_MAJOR_VERSION ? "message" : (this->is_request ? "request" : "response")); @@ -2463,7 +2477,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) was_encrypted = "encrypted fragment payload"; } - if (payload_is_known(type) && !was_encrypted && + if (payload_is_known(type, this->major_version) && !was_encrypted && !is_connectivity_check(this, payload) && this->exchange_type != AGGRESSIVE) { diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c index d6240fde2..f8340367e 100644 --- a/src/libcharon/encoding/parser.c +++ b/src/libcharon/encoding/parser.c @@ -59,6 +59,11 @@ struct private_parser_t { parser_t public; /** + * major IKE version + */ + u_int8_t major_version; + + /** * Current bit for reading in input data. */ u_int8_t bit_pos; @@ -369,7 +374,14 @@ METHOD(parser_t, parse_payload, status_t, encoding_rule_t *rule; /* create instance of the payload to parse */ - pld = payload_create(payload_type); + if (payload_is_known(payload_type, this->major_version)) + { + pld = payload_create(payload_type); + } + else + { + pld = (payload_t*)unknown_payload_create(payload_type); + } DBG2(DBG_ENC, "parsing %N payload, %d bytes left", payload_type_names, payload_type, this->input_roof - this->byte_pos); @@ -629,6 +641,12 @@ METHOD(parser_t, reset_context, void, this->bit_pos = 0; } +METHOD(parser_t, set_major_version, void, + private_parser_t *this, u_int8_t major_version) +{ + this->major_version = major_version; +} + METHOD(parser_t, destroy, void, private_parser_t *this) { @@ -646,6 +664,7 @@ parser_t *parser_create(chunk_t data) .public = { .parse_payload = _parse_payload, .reset_context = _reset_context, + .set_major_version = _set_major_version, .get_remaining_byte_count = _get_remaining_byte_count, .destroy = _destroy, }, diff --git a/src/libcharon/encoding/parser.h b/src/libcharon/encoding/parser.h index 27c5f03fe..5fd3e86ee 100644 --- a/src/libcharon/encoding/parser.h +++ b/src/libcharon/encoding/parser.h @@ -29,7 +29,7 @@ typedef struct parser_t parser_t; #include <encoding/payloads/payload.h> /** - * A parser_t class to parse IKEv2 payloads. + * A parser_t class to parse IKE payloads. * * A parser is used for parsing one chunk of data. Multiple * payloads can be parsed out of the chunk using parse_payload. @@ -50,7 +50,8 @@ struct parser_t { * - SUCCESSFUL if succeeded, * - PARSE_ERROR if corrupted/invalid data found */ - status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, payload_t **payload); + status_t (*parse_payload) (parser_t *this, payload_type_t payload_type, + payload_t **payload); /** * Gets the remaining byte count which is not currently parsed. @@ -63,6 +64,13 @@ struct parser_t { void (*reset_context) (parser_t *this); /** + * Set the major IKE version. + * + * @param major_version the major IKE version + */ + void (*set_major_version) (parser_t *this, u_int8_t major_version); + + /** * Destroys a parser_t object. */ void (*destroy) (parser_t *this); diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c index c2ab3b951..f11ea485c 100644 --- a/src/libcharon/encoding/payloads/delete_payload.c +++ b/src/libcharon/encoding/payloads/delete_payload.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2015 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2010 revosec AG * Copyright (C) 2005 Jan Hutter @@ -281,6 +282,19 @@ METHOD(delete_payload_t, set_ike_spi, void, this->payload_length = get_header_length(this) + this->spi_size; } +METHOD(delete_payload_t, get_ike_spi, bool, + private_delete_payload_t *this, u_int64_t *spi_i, u_int64_t *spi_r) +{ + if (this->protocol_id != PROTO_IKE || + this->spis.len < 2 * sizeof(u_int64_t)) + { + return FALSE; + } + memcpy(spi_i, this->spis.ptr, sizeof(u_int64_t)); + memcpy(spi_r, this->spis.ptr + sizeof(u_int64_t), sizeof(u_int64_t)); + return TRUE; +} + /** * SPI enumerator implementation */ @@ -352,6 +366,7 @@ delete_payload_t *delete_payload_create(payload_type_t type, .get_protocol_id = _get_protocol_id, .add_spi = _add_spi, .set_ike_spi = _set_ike_spi, + .get_ike_spi = _get_ike_spi, .create_spi_enumerator = _create_spi_enumerator, .destroy = _destroy, }, diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h index 46a89eab6..6728718cd 100644 --- a/src/libcharon/encoding/payloads/delete_payload.h +++ b/src/libcharon/encoding/payloads/delete_payload.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2015 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -61,6 +62,15 @@ struct delete_payload_t { void (*set_ike_spi)(delete_payload_t *this, u_int64_t spi_i, u_int64_t spi_r); /** + * Get the IKE SPIs from an IKEv1 delete. + * + * @param spi_i initiator SPI + * @param spi_r responder SPI + * @return TRUE if SPIs extracted successfully + */ + bool (*get_ike_spi)(delete_payload_t *this, u_int64_t *spi_i, u_int64_t *spi_r); + + /** * Get an enumerator over the SPIs in network order. * * @return enumerator over SPIs, u_int32_t diff --git a/src/libcharon/encoding/payloads/encrypted_payload.c b/src/libcharon/encoding/payloads/encrypted_payload.c index 5c574c34d..04372fdf0 100644 --- a/src/libcharon/encoding/payloads/encrypted_payload.c +++ b/src/libcharon/encoding/payloads/encrypted_payload.c @@ -561,6 +561,7 @@ static status_t parse(private_encrypted_payload_t *this, chunk_t plain) payload_type_t type; parser = parser_create(plain); + parser->set_major_version(parser, this->type == PLV1_ENCRYPTED ? 1 : 2); type = this->next_payload; while (type != PL_NONE) { diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c index a002a8f21..bb8aab748 100644 --- a/src/libcharon/encoding/payloads/id_payload.c +++ b/src/libcharon/encoding/payloads/id_payload.c @@ -258,17 +258,20 @@ static traffic_selector_t *get_ts_from_range(private_id_payload_t *this, static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this, ts_type_t type) { + traffic_selector_t *ts; chunk_t net, netmask; int i; net = chunk_create(this->id_data.ptr, this->id_data.len / 2); - netmask = chunk_skip(this->id_data, this->id_data.len / 2); + netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2)); for (i = 0; i < net.len; i++) { netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i]; } - return traffic_selector_create_from_bytes(this->protocol_id, type, + ts = traffic_selector_create_from_bytes(this->protocol_id, type, net, this->port, netmask, this->port ?: 65535); + chunk_free(&netmask); + return ts; } /** diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c index 4f552d6ac..50fd73f90 100644 --- a/src/libcharon/encoding/payloads/ke_payload.c +++ b/src/libcharon/encoding/payloads/ke_payload.c @@ -247,9 +247,15 @@ ke_payload_t *ke_payload_create(payload_type_t type) ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type, diffie_hellman_t *dh) { - private_ke_payload_t *this = (private_ke_payload_t*)ke_payload_create(type); + private_ke_payload_t *this; + chunk_t value; - dh->get_my_public_value(dh, &this->key_exchange_data); + if (!dh->get_my_public_value(dh, &value)) + { + return NULL; + } + this = (private_ke_payload_t*)ke_payload_create(type); + this->key_exchange_data = value; this->dh_group_number = dh->get_dh_group(dh); this->payload_length += this->key_exchange_data.len; diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h index dfc6308b4..96c5096a5 100644 --- a/src/libcharon/encoding/payloads/ke_payload.h +++ b/src/libcharon/encoding/payloads/ke_payload.h @@ -73,7 +73,7 @@ ke_payload_t *ke_payload_create(payload_type_t type); * * @param type PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE * @param dh diffie hellman object containing group and key - * @return ke_payload_t object + * @return ke_payload_t object, NULL on error */ ke_payload_t *ke_payload_create_from_diffie_hellman(payload_type_t type, diffie_hellman_t *dh); diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c index 94723ddd7..f32a1273f 100644 --- a/src/libcharon/encoding/payloads/notify_payload.c +++ b/src/libcharon/encoding/payloads/notify_payload.c @@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_ "ME_CONNECT_FAILED"); ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED, "MS_NOTIFY_STATUS"); -ENUM_NEXT(notify_type_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS, +ENUM_NEXT(notify_type_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, MS_NOTIFY_STATUS, "INITIAL_CONTACT", "SET_WINDOW_SIZE", "ADDITIONAL_TS_POSSIBLE", @@ -112,8 +112,9 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY "ERX_SUPPORTED", "IFOM_CAPABILITY", "SENDER_REQUEST_ID", - "FRAGMENTATION_SUPPORTED"); -ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED, + "FRAGMENTATION_SUPPORTED", + "SIGNATURE_HASH_ALGORITHMS"); +ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS, "INITIAL_CONTACT"); ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, "DPD_R_U_THERE", @@ -174,7 +175,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S "ME_CONN_FAIL"); ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED, "MS_STATUS"); -ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS, +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, SIGNATURE_HASH_ALGORITHMS, MS_NOTIFY_STATUS, "INIT_CONTACT", "SET_WINSIZE", "ADD_TS_POSS", @@ -221,8 +222,9 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_ "ERX_SUP", "IFOM_CAP", "SENDER_REQ_ID", - "FRAG_SUP"); -ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED, + "FRAG_SUP", + "HASH_ALG"); +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, SIGNATURE_HASH_ALGORITHMS, "INITIAL_CONTACT"); ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, "DPD", @@ -473,6 +475,14 @@ METHOD(payload_t, verify, status_t, } break; } + case SIGNATURE_HASH_ALGORITHMS: + { + if (this->notify_data.len % 2) + { + bad_length = TRUE; + } + break; + } case AUTH_LIFETIME: { if (this->notify_data.len != 4) diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h index 25521c2bb..690757383 100644 --- a/src/libcharon/encoding/payloads/notify_payload.h +++ b/src/libcharon/encoding/payloads/notify_payload.h @@ -151,6 +151,8 @@ enum notify_type_t { SENDER_REQUEST_ID = 16429, /* IKEv2 fragmentation supported, RFC 7383 */ FRAGMENTATION_SUPPORTED = 16430, + /* Signature Hash Algorithms, RFC 7427 */ + SIGNATURE_HASH_ALGORITHMS = 16431, /* IKEv1 initial contact */ INITIAL_CONTACT_IKEV1 = 24578, /* IKEv1 DPD */ diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index 600b6dd68..a1cd2f945 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -266,37 +266,51 @@ payload_t *payload_create(payload_type_t type) /** * See header. */ -bool payload_is_known(payload_type_t type) +bool payload_is_known(payload_type_t type, u_int8_t maj_ver) { - if (type == PL_HEADER) + if (type >= PL_HEADER) { return TRUE; } - if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION) + switch (maj_ver) { - return TRUE; - } - if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA) - { - return TRUE; - } - if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP) - { - return TRUE; - } - if (type == PLV2_FRAGMENT) - { - return TRUE; - } + case 0: + case IKEV1_MAJOR_VERSION: + if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION) + { + return TRUE; + } + if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA) + { + return TRUE; + } + if (type >= PLV1_NAT_D_DRAFT_00_03 && type <= PLV1_FRAGMENT) + { + return TRUE; + } + if (maj_ver) + { + break; + } + /* fall-through */ + case IKEV2_MAJOR_VERSION: + if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP) + { + return TRUE; + } + if (type == PLV2_FRAGMENT) + { + return TRUE; + } #ifdef ME - if (type == PLV2_ID_PEER) - { - return TRUE; - } + if (type == PLV2_ID_PEER) + { + return TRUE; + } #endif - if (type >= PLV1_NAT_D_DRAFT_00_03 && type <= PLV1_FRAGMENT) - { - return TRUE; + break; + default: + break; } return FALSE; } diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h index 036cd422d..920779bd1 100644 --- a/src/libcharon/encoding/payloads/payload.h +++ b/src/libcharon/encoding/payloads/payload.h @@ -405,9 +405,10 @@ payload_t *payload_create(payload_type_t type); * Check if a specific payload is implemented, or handled as unknown payload. * * @param type type of the payload to check + * @param maj_ver major IKE version (use 0 to skip version check) * @return FALSE if payload type handled as unknown payload */ -bool payload_is_known(payload_type_t type); +bool payload_is_known(payload_type_t type, u_int8_t maj_ver); /** * Get the value field in a payload using encoding rules. diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c index 53e8cf3ad..48dcfeb24 100644 --- a/src/libcharon/encoding/payloads/proposal_substructure.c +++ b/src/libcharon/encoding/payloads/proposal_substructure.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2014 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -224,26 +224,7 @@ typedef enum { /* FreeS/WAN proprietary */ IKEV1_ESP_ENCR_SERPENT = 252, IKEV1_ESP_ENCR_TWOFISH = 253, -} ikev1_esp_encr_transid_t; - -/** - * IKEv1 Transform ID ESP authentication algorithm. - */ -typedef enum { - IKEV1_ESP_AUTH_HMAC_MD5 = 1, - IKEV1_ESP_AUTH_HMAC_SHA = 2, - IKEV1_ESP_AUTH_DES_MAC = 3, - IKEV1_ESP_AUTH_KPDK = 4, - IKEV1_ESP_AUTH_HMAC_SHA2_256 = 5, - IKEV1_ESP_AUTH_HMAC_SHA2_384 = 6, - IKEV1_ESP_AUTH_HMAC_SHA2_512 = 7, - IKEV1_ESP_AUTH_HMAC_RIPEMD = 8, - IKEV1_ESP_AUTH_AES_XCBC_MAC = 9, - IKEV1_ESP_AUTH_SIG_RSA = 10, - IKEV1_ESP_AUTH_AES_128_GMAC = 11, - IKEV1_ESP_AUTH_AES_192_GMAC = 12, - IKEV1_ESP_AUTH_AES_256_GMAC = 13, -} ikev1_esp_auth_transid_it; +} ikev1_esp_transid_t; /** * IKEv1 Transform ID AH authentication algorithm. @@ -264,6 +245,25 @@ typedef enum { } ikev1_ah_transid_t; /** + * IKEv1 authentication algorithm. + */ +typedef enum { + IKEV1_AUTH_HMAC_MD5 = 1, + IKEV1_AUTH_HMAC_SHA = 2, + IKEV1_AUTH_DES_MAC = 3, + IKEV1_AUTH_KPDK = 4, + IKEV1_AUTH_HMAC_SHA2_256 = 5, + IKEV1_AUTH_HMAC_SHA2_384 = 6, + IKEV1_AUTH_HMAC_SHA2_512 = 7, + IKEV1_AUTH_HMAC_RIPEMD = 8, + IKEV1_AUTH_AES_XCBC_MAC = 9, + IKEV1_AUTH_SIG_RSA = 10, + IKEV1_AUTH_AES_128_GMAC = 11, + IKEV1_AUTH_AES_192_GMAC = 12, + IKEV1_AUTH_AES_256_GMAC = 13, +} ikev1_auth_algo_t; + +/** * IKEv1 ESP Encapsulation mode. */ typedef enum { @@ -345,7 +345,7 @@ METHOD(payload_t, verify, status_t, switch (this->protocol_id) { case PROTO_IPCOMP: - if (this->spi.len != 2) + if (this->spi.len != 2 && this->spi.len != 4) { DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal"); return FAILED; @@ -536,7 +536,7 @@ METHOD(proposal_substructure_t, get_cpi, bool, { if (cpi) { - *cpi = *((u_int16_t*)this->spi.ptr); + *cpi = htons(untoh16(this->spi.ptr + this->spi.len - 2)); } enumerator->destroy(enumerator); return TRUE; @@ -620,7 +620,7 @@ static algo_map_t map_prf[] = { /** * ESP encryption algorithm mapping */ -static algo_map_t map_esp_encr[] = { +static algo_map_t map_esp[] = { { IKEV1_ESP_ENCR_DES_IV64, ENCR_DES_IV64 }, { IKEV1_ESP_ENCR_DES, ENCR_DES }, { IKEV1_ESP_ENCR_3DES, ENCR_3DES }, @@ -646,23 +646,6 @@ static algo_map_t map_esp_encr[] = { }; /** - * ESP authentication algorithm mapping - */ -static algo_map_t map_esp_auth[] = { - { IKEV1_ESP_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 }, - { IKEV1_ESP_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 }, - { IKEV1_ESP_AUTH_DES_MAC, AUTH_DES_MAC }, - { IKEV1_ESP_AUTH_KPDK, AUTH_KPDK_MD5 }, - { IKEV1_ESP_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 }, - { IKEV1_ESP_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 }, - { IKEV1_ESP_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 }, - { IKEV1_ESP_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 }, - { IKEV1_ESP_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC }, - { IKEV1_ESP_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC }, - { IKEV1_ESP_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC }, -}; - -/** * AH authentication algorithm mapping */ static algo_map_t map_ah[] = { @@ -679,34 +662,30 @@ static algo_map_t map_ah[] = { }; /** - * Get IKEv2 algorithm from IKEv1 identifier + * ESP/AH authentication algorithm mapping */ -static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value) +static algo_map_t map_auth[] = { + { IKEV1_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 }, + { IKEV1_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 }, + { IKEV1_AUTH_DES_MAC, AUTH_DES_MAC }, + { IKEV1_AUTH_KPDK, AUTH_KPDK_MD5 }, + { IKEV1_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 }, + { IKEV1_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 }, + { IKEV1_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 }, + { IKEV1_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 }, + { IKEV1_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC }, + { IKEV1_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC }, + { IKEV1_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC }, +}; + +/** + * Map an IKEv1 to an IKEv2 identifier + */ +static u_int16_t ikev2_from_ikev1(algo_map_t *map, int count, u_int16_t def, + u_int16_t value) { - algo_map_t *map; - u_int16_t def; - int i, count; + int i; - switch (type) - { - case ENCRYPTION_ALGORITHM: - map = map_encr; - count = countof(map_encr); - def = ENCR_UNDEFINED; - break; - case INTEGRITY_ALGORITHM: - map = map_integ; - count = countof(map_integ); - def = AUTH_UNDEFINED; - break; - case PSEUDO_RANDOM_FUNCTION: - map = map_prf; - count = countof(map_prf); - def = PRF_UNDEFINED; - break; - default: - return 0; - } for (i = 0; i < count; i++) { if (map[i].ikev1 == value) @@ -718,30 +697,12 @@ static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value) } /** - * Get IKEv1 algorithm from IKEv2 identifier + * Map an IKEv2 to an IKEv1 identifier */ -static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value) +static u_int16_t ikev1_from_ikev2(algo_map_t *map, int count, u_int16_t value) { - algo_map_t *map; - int i, count; + int i; - switch (type) - { - case ENCRYPTION_ALGORITHM: - map = map_encr; - count = countof(map_encr); - break; - case INTEGRITY_ALGORITHM: - map = map_integ; - count = countof(map_integ); - break; - case PSEUDO_RANDOM_FUNCTION: - map = map_prf; - count = countof(map_prf); - break; - default: - return 0; - } for (i = 0; i < count; i++) { if (map[i].ikev2 == value) @@ -753,87 +714,96 @@ static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value) } /** - * Get IKEv2 algorithm from IKEv1 ESP transaction ID + * Get IKEv2 algorithm from IKEv1 identifier */ -static u_int16_t get_alg_from_ikev1_transid(protocol_id_t proto, - transform_type_t type, u_int16_t value) +static u_int16_t get_alg_from_ikev1(transform_type_t type, u_int16_t value) { - algo_map_t *map; - u_int16_t def; - int i, count; - switch (type) { case ENCRYPTION_ALGORITHM: - map = map_esp_encr; - count = countof(map_esp_encr); - def = ENCR_UNDEFINED; - break; + return ikev2_from_ikev1(map_encr, countof(map_encr), + ENCR_UNDEFINED, value); case INTEGRITY_ALGORITHM: - if (proto == PROTO_ESP) - { - map = map_esp_auth; - count = countof(map_esp_auth); - } - else - { - map = map_ah; - count = countof(map_ah); - } - def = AUTH_UNDEFINED; - break; + return ikev2_from_ikev1(map_integ, countof(map_integ), + AUTH_UNDEFINED, value); + case PSEUDO_RANDOM_FUNCTION: + return ikev2_from_ikev1(map_prf, countof(map_prf), + PRF_UNDEFINED, value); default: return 0; } - for (i = 0; i < count; i++) +} + +/** + * Get IKEv1 algorithm from IKEv2 identifier + */ +static u_int16_t get_ikev1_from_alg(transform_type_t type, u_int16_t value) +{ + switch (type) { - if (map[i].ikev1 == value) - { - return map[i].ikev2; - } + case ENCRYPTION_ALGORITHM: + return ikev1_from_ikev2(map_encr, countof(map_encr), value); + case INTEGRITY_ALGORITHM: + return ikev1_from_ikev2(map_integ, countof(map_integ), value); + case PSEUDO_RANDOM_FUNCTION: + return ikev1_from_ikev2(map_prf, countof(map_prf), value); + default: + return 0; } - return def; } /** - * Get IKEv1 ESP/AH transaction ID from IKEv2 identifier + * Get IKEv2 algorithm from IKEv1 ESP/AH transform ID */ -static u_int16_t get_ikev1_transid_from_alg(protocol_id_t proto, - transform_type_t type, u_int16_t value) +static u_int16_t get_alg_from_ikev1_transid(transform_type_t type, + u_int16_t value) { - algo_map_t *map; - int i, count; - switch (type) { case ENCRYPTION_ALGORITHM: - map = map_esp_encr; - count = countof(map_esp_encr); - break; + return ikev2_from_ikev1(map_esp, countof(map_esp), + ENCR_UNDEFINED, value); case INTEGRITY_ALGORITHM: - if (proto == PROTO_ESP) - { - map = map_esp_auth; - count = countof(map_esp_auth); - } - else - { - map = map_ah; - count = countof(map_ah); - } - break; + return ikev2_from_ikev1(map_ah, countof(map_ah), + AUTH_UNDEFINED, value); default: return 0; } - for (i = 0; i < count; i++) +} + +/** + * Get IKEv1 ESP/AH transform ID from IKEv2 identifier + */ +static u_int16_t get_ikev1_transid_from_alg(transform_type_t type, + u_int16_t value) +{ + switch (type) { - if (map[i].ikev2 == value) - { - return map[i].ikev1; - } + case ENCRYPTION_ALGORITHM: + return ikev1_from_ikev2(map_esp, countof(map_esp), value); + case INTEGRITY_ALGORITHM: + return ikev1_from_ikev2(map_ah, countof(map_ah), value); + default: + return 0; } - return 0; } + +/** + * Get IKEv1 authentication algorithm from IKEv2 identifier + */ +static u_int16_t get_alg_from_ikev1_auth(u_int16_t value) +{ + return ikev2_from_ikev1(map_auth, countof(map_auth), AUTH_UNDEFINED, value); +} + +/** + * Get IKEv1 authentication algorithm from IKEv2 identifier + */ +static u_int16_t get_ikev1_auth_from_alg(u_int16_t value) +{ + return ikev1_from_ikev2(map_auth, countof(map_auth), value); +} + /** * Get IKEv1 authentication attribute from auth_method_t */ @@ -971,8 +941,7 @@ static void add_to_proposal_v1(proposal_t *proposal, break; case TATTR_PH2_AUTH_ALGORITHM: proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, - get_alg_from_ikev1_transid(proto, INTEGRITY_ALGORITHM, - value), 0); + get_alg_from_ikev1_auth(value), 0); break; case TATTR_PH2_GROUP: proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, @@ -989,7 +958,7 @@ static void add_to_proposal_v1(proposal_t *proposal, NO_EXT_SEQ_NUMBERS, 0); if (proto == PROTO_ESP) { - encr = get_alg_from_ikev1_transid(proto, ENCRYPTION_ALGORITHM, + encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM, transform->get_transform_id(transform)); if (encr) { @@ -1354,19 +1323,17 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this, ipsec_mode_t mode, encap_t udp, int number) { transform_substructure_t *transform = NULL; - u_int16_t alg, key_size; + u_int16_t alg, transid, key_size; enumerator_t *enumerator; - protocol_id_t proto; - proto = proposal->get_protocol(proposal); enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM); if (enumerator->enumerate(enumerator, &alg, &key_size)) { - alg = get_ikev1_transid_from_alg(proto, ENCRYPTION_ALGORITHM, alg); - if (alg) + transid = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg); + if (transid) { transform = transform_substructure_create_type( - PLV1_TRANSFORM_SUBSTRUCTURE, number, alg); + PLV1_TRANSFORM_SUBSTRUCTURE, number, transid); if (key_size) { transform->add_transform_attribute(transform, @@ -1380,13 +1347,14 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this, enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM); if (enumerator->enumerate(enumerator, &alg, &key_size)) { - alg = get_ikev1_transid_from_alg(proto, INTEGRITY_ALGORITHM, alg); - if (alg) + transid = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg); + alg = get_ikev1_auth_from_alg(alg); + if (transid && alg) { if (!transform) { transform = transform_substructure_create_type( - PLV1_TRANSFORM_SUBSTRUCTURE, number, alg); + PLV1_TRANSFORM_SUBSTRUCTURE, number, transid); } transform->add_transform_attribute(transform, transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE, diff --git a/src/libcharon/kernel/kernel_handler.c b/src/libcharon/kernel/kernel_handler.c index 059124e35..9c0e2602b 100644 --- a/src/libcharon/kernel/kernel_handler.c +++ b/src/libcharon/kernel/kernel_handler.c @@ -72,36 +72,39 @@ METHOD(kernel_listener_t, acquire, bool, } METHOD(kernel_listener_t, expire, bool, - private_kernel_handler_t *this, u_int32_t reqid, u_int8_t protocol, - u_int32_t spi, bool hard) + private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, bool hard) { protocol_id_t proto = proto_ip2ike(protocol); - DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%u}", - hard ? "delete" : "rekey", protocol_id_names, proto, ntohl(spi), reqid); + DBG1(DBG_KNL, "creating %s job for CHILD_SA %N/0x%08x/%H", + hard ? "delete" : "rekey", protocol_id_names, proto, ntohl(spi), dst); if (hard) { lib->processor->queue_job(lib->processor, - (job_t*)delete_child_sa_job_create(reqid, proto, spi, hard)); + (job_t*)delete_child_sa_job_create(proto, spi, dst, hard)); } else { lib->processor->queue_job(lib->processor, - (job_t*)rekey_child_sa_job_create(reqid, proto, spi)); + (job_t*)rekey_child_sa_job_create(proto, spi, dst)); } return TRUE; } METHOD(kernel_listener_t, mapping, bool, - private_kernel_handler_t *this, u_int32_t reqid, u_int32_t spi, - host_t *remote) + private_kernel_handler_t *this, u_int8_t protocol, u_int32_t spi, + host_t *dst, host_t *remote) { - DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and reqid {%u} " - "changed, queuing update job", ntohl(spi), reqid); + protocol_id_t proto = proto_ip2ike(protocol); + + DBG1(DBG_KNL, "NAT mappings of CHILD_SA %N/0x%08x/%H changed to %#H, " + "queuing update job", protocol_id_names, proto, ntohl(spi), dst, + remote); lib->processor->queue_job(lib->processor, - (job_t*)update_sa_job_create(reqid, remote)); + (job_t*)update_sa_job_create(proto, spi, dst, remote)); return TRUE; } diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in index c3b014c3c..0554465b9 100644 --- a/src/libcharon/plugins/addrblock/Makefile.in +++ b/src/libcharon/plugins/addrblock/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in index 50594a452..58cf97b6e 100644 --- a/src/libcharon/plugins/android_dns/Makefile.in +++ b/src/libcharon/plugins/android_dns/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/android_dns/android_dns_handler.c b/src/libcharon/plugins/android_dns/android_dns_handler.c index 526810355..160a145d3 100644 --- a/src/libcharon/plugins/android_dns/android_dns_handler.c +++ b/src/libcharon/plugins/android_dns/android_dns_handler.c @@ -128,7 +128,7 @@ static bool set_dns_server(private_android_dns_handler_t *this, int index, } METHOD(attribute_handler_t, handle, bool, - private_android_dns_handler_t *this, identification_t *id, + private_android_dns_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -158,7 +158,7 @@ METHOD(attribute_handler_t, handle, bool, } METHOD(attribute_handler_t, release, void, - private_android_dns_handler_t *this, identification_t *server, + private_android_dns_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { if (type == INTERNAL_IP4_DNS) @@ -192,7 +192,7 @@ METHOD(enumerator_t, enumerate_dns, bool, } METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, - private_android_dns_handler_t *this, identification_t *id, + private_android_dns_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips) { enumerator_t *enumerator; @@ -232,4 +232,3 @@ android_dns_handler_t *android_dns_handler_create() return &this->public; } - diff --git a/src/libcharon/plugins/android_dns/android_dns_plugin.c b/src/libcharon/plugins/android_dns/android_dns_plugin.c index b8eb11b57..9b6ec0dba 100644 --- a/src/libcharon/plugins/android_dns/android_dns_plugin.c +++ b/src/libcharon/plugins/android_dns/android_dns_plugin.c @@ -16,7 +16,6 @@ #include "android_dns_plugin.h" #include "android_dns_handler.h" -#include <hydra.h> #include <daemon.h> typedef struct private_android_dns_plugin_t private_android_dns_plugin_t; @@ -51,13 +50,13 @@ static bool plugin_cb(private_android_dns_plugin_t *this, { if (reg) { - hydra->attributes->add_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); } else { - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); } return TRUE; } diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in index 700a4219c..8ce92e577 100644 --- a/src/libcharon/plugins/android_log/Makefile.in +++ b/src/libcharon/plugins/android_log/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/attr/Makefile.am b/src/libcharon/plugins/attr/Makefile.am new file mode 100644 index 000000000..6bc7e77d8 --- /dev/null +++ b/src/libcharon/plugins/attr/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-attr.la +else +plugin_LTLIBRARIES = libstrongswan-attr.la +endif + +libstrongswan_attr_la_SOURCES = \ + attr_plugin.h attr_plugin.c \ + attr_provider.h attr_provider.c + +libstrongswan_attr_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/attr/Makefile.in b/src/libcharon/plugins/attr/Makefile.in new file mode 100644 index 000000000..486b3c0b0 --- /dev/null +++ b/src/libcharon/plugins/attr/Makefile.in @@ -0,0 +1,777 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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/attr +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +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__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +libstrongswan_attr_la_LIBADD = +am_libstrongswan_attr_la_OBJECTS = attr_plugin.lo attr_provider.lo +libstrongswan_attr_la_OBJECTS = $(am_libstrongswan_attr_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_attr_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_attr_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_attr_la_rpath = -rpath $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_attr_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_attr_la_SOURCES) +DIST_SOURCES = $(libstrongswan_attr_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-attr.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-attr.la +libstrongswan_attr_la_SOURCES = \ + attr_plugin.h attr_plugin.c \ + attr_provider.h attr_provider.c + +libstrongswan_attr_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/attr/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/attr/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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @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 " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + 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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-attr.la: $(libstrongswan_attr_la_OBJECTS) $(libstrongswan_attr_la_DEPENDENCIES) $(EXTRA_libstrongswan_attr_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_attr_la_LINK) $(am_libstrongswan_attr_la_rpath) $(libstrongswan_attr_la_OBJECTS) $(libstrongswan_attr_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_provider.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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 TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am 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 tags-am 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/attr/attr_plugin.c b/src/libcharon/plugins/attr/attr_plugin.c new file mode 100644 index 000000000..9b15c3cc9 --- /dev/null +++ b/src/libcharon/plugins/attr/attr_plugin.c @@ -0,0 +1,109 @@ +/* + * 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 "attr_plugin.h" +#include "attr_provider.h" + +#include <daemon.h> + +typedef struct private_attr_plugin_t private_attr_plugin_t; + +/** + * private data of attr plugin + */ +struct private_attr_plugin_t { + + /** + * implements plugin interface + */ + attr_plugin_t public; + + /** + * CFG attributes provider + */ + attr_provider_t *provider; +}; + +METHOD(plugin_t, get_name, char*, + private_attr_plugin_t *this) +{ + return "attr"; +} + +/** + * Register provider + */ +static bool plugin_cb(private_attr_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->attributes->add_provider(charon->attributes, + &this->provider->provider); + } + else + { + charon->attributes->remove_provider(charon->attributes, + &this->provider->provider); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_attr_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "attr"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, reload, bool, + private_attr_plugin_t *this) +{ + this->provider->reload(this->provider); + return TRUE; +} + +METHOD(plugin_t, destroy, void, + private_attr_plugin_t *this) +{ + this->provider->destroy(this->provider); + free(this); +} + +/* + * see header file + */ +plugin_t *attr_plugin_create() +{ + private_attr_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .reload = _reload, + .destroy = _destroy, + }, + }, + .provider = attr_provider_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/unit_tester/tests.h b/src/libcharon/plugins/attr/attr_plugin.h index 169292e9b..0c6eebfa7 100644 --- a/src/libcharon/plugins/unit_tester/tests.h +++ b/src/libcharon/plugins/attr/attr_plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2009 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,17 +14,29 @@ */ /** - * @defgroup tests tests - * @{ @ingroup unit_tester + * @defgroup attr attr + * @ingroup cplugins + * + * @defgroup attr_plugin attr_plugin + * @{ @ingroup attr + */ + +#ifndef ATTR_PLUGIN_H_ +#define ATTR_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct attr_plugin_t attr_plugin_t; + +/** + * Plugin providing configuration attribute through strongswan.conf. */ +struct attr_plugin_t { -DEFINE_TEST("auth cfg", test_auth_cfg, FALSE) -DEFINE_TEST("CURL get", test_curl_get, FALSE) -DEFINE_TEST("MySQL operations", test_mysql, FALSE) -DEFINE_TEST("SQLite operations", test_sqlite, FALSE) -DEFINE_TEST("X509 certificate", test_cert_x509, FALSE) -DEFINE_TEST("Mediation database key fetch", test_med_db, FALSE) -DEFINE_TEST("IP pool", test_pool, FALSE) -DEFINE_TEST("SSH agent", test_agent, FALSE) + /** + * implements plugin interface + */ + plugin_t plugin; +}; -/** @}*/ +#endif /** ATTR_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c new file mode 100644 index 000000000..cac0ae4bf --- /dev/null +++ b/src/libcharon/plugins/attr/attr_provider.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2010 Tobias Brunner + * 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 "attr_provider.h" + +#include <time.h> + +#include <daemon.h> +#include <utils/debug.h> +#include <collections/linked_list.h> +#include <threading/rwlock.h> + +#define SERVER_MAX 2 + +typedef struct private_attr_provider_t private_attr_provider_t; +typedef struct attribute_entry_t attribute_entry_t; + +/** + * private data of attr_provider + */ +struct private_attr_provider_t { + + /** + * public functions + */ + attr_provider_t public; + + /** + * List of attributes, attribute_entry_t + */ + linked_list_t *attributes; + + /** + * Lock for attribute list + */ + rwlock_t *lock; +}; + +struct attribute_entry_t { + /** type of attribute */ + configuration_attribute_type_t type; + /** attribute value */ + chunk_t value; +}; + +/** + * Destroy an entry + */ +static void attribute_destroy(attribute_entry_t *this) +{ + free(this->value.ptr); + free(this); +} + +/** + * convert enumerator value from attribute_entry + */ +static bool attr_enum_filter(void *null, attribute_entry_t **in, + configuration_attribute_type_t *type, void* none, chunk_t *value) +{ + *type = (*in)->type; + *value = (*in)->value; + return TRUE; +} + +METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, + private_attr_provider_t *this, linked_list_t *pools, + ike_sa_t *ike_sa, linked_list_t *vips) +{ + if (vips->get_count(vips)) + { + this->lock->read_lock(this->lock); + return enumerator_create_filter( + this->attributes->create_enumerator(this->attributes), + (void*)attr_enum_filter, this->lock, (void*)this->lock->unlock); + } + return enumerator_create_empty(); +} + +METHOD(attr_provider_t, destroy, void, + private_attr_provider_t *this) +{ + this->attributes->destroy_function(this->attributes, + (void*)attribute_destroy); + this->lock->destroy(this->lock); + free(this); +} + +/** + * Add an attribute entry to the list + */ +static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr, + configuration_attribute_type_t type) +{ + attribute_entry_t *entry; + host_t *host; + char *str; + + str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, lib->ns, + key, nr); + if (str) + { + host = host_create_from_string(str, 0); + if (host) + { + entry = malloc_thing(attribute_entry_t); + + if (host->get_family(host) == AF_INET6) + { + switch (type) + { + case INTERNAL_IP4_DNS: + type = INTERNAL_IP6_DNS; + break; + case INTERNAL_IP4_NBNS: + type = INTERNAL_IP6_NBNS; + break; + default: + break; + } + } + entry->type = type; + entry->value = chunk_clone(host->get_address(host)); + host->destroy(host); + DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B", + configuration_attribute_type_names, entry->type, &entry->value); + this->attributes->insert_last(this->attributes, entry); + } + } +} + +/** + * Key to attribute type mappings, for v4 and v6 attributes + */ +typedef struct { + char *name; + configuration_attribute_type_t v4; + configuration_attribute_type_t v6; +} attribute_type_key_t; + +static attribute_type_key_t keys[] = { + {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS}, + {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS}, + {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS}, + {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP}, + {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK}, + {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER}, + {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET}, + {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE}, + {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN}, +}; + +/** + * Load (numerical) entries from the plugins.attr namespace + */ +static void load_entries(private_attr_provider_t *this) +{ + enumerator_t *enumerator, *tokens; + char *key, *value, *token; + int i; + + for (i = 1; i <= SERVER_MAX; i++) + { + add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS); + add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS); + } + + enumerator = lib->settings->create_key_value_enumerator(lib->settings, + "%s.plugins.attr", lib->ns); + while (enumerator->enumerate(enumerator, &key, &value)) + { + configuration_attribute_type_t type; + attribute_type_key_t *mapped = NULL; + attribute_entry_t *entry; + chunk_t data; + host_t *host; + char *pos; + int i, mask = -1, family; + + if (streq(key, "load")) + { + continue; + } + type = atoi(key); + if (!type) + { + for (i = 0; i < countof(keys); i++) + { + if (streq(key, keys[i].name)) + { + mapped = &keys[i]; + break; + } + } + if (!mapped) + { + DBG1(DBG_CFG, "mapping attribute type %s failed", key); + continue; + } + } + tokens = enumerator_create_token(value, ",", " "); + while (tokens->enumerate(tokens, &token)) + { + pos = strchr(token, '/'); + if (pos) + { + *(pos++) = '\0'; + mask = atoi(pos); + } + host = host_create_from_string(token, 0); + if (!host) + { + if (mapped) + { + DBG1(DBG_CFG, "invalid host in key %s: %s", key, token); + continue; + } + /* store numeric attributes that are no IP addresses as strings */ + data = chunk_clone(chunk_from_str(token)); + } + else + { + family = host->get_family(host); + if (mask == -1) + { + data = chunk_clone(host->get_address(host)); + } + else + { + if (family == AF_INET) + { /* IPv4 attributes contain a subnet mask */ + u_int32_t netmask = 0; + + if (mask) + { /* shifting u_int32_t by 32 or more is undefined */ + mask = 32 - mask; + netmask = htonl((0xFFFFFFFF >> mask) << mask); + } + data = chunk_cat("cc", host->get_address(host), + chunk_from_thing(netmask)); + } + else + { /* IPv6 addresses the prefix only */ + data = chunk_cat("cc", host->get_address(host), + chunk_from_chars(mask)); + } + } + host->destroy(host); + if (mapped) + { + switch (family) + { + case AF_INET: + type = mapped->v4; + break; + case AF_INET6: + type = mapped->v6; + break; + } + } + } + INIT(entry, + .type = type, + .value = data, + ); + DBG2(DBG_CFG, "loaded attribute %N: %#B", + configuration_attribute_type_names, entry->type, &entry->value); + this->attributes->insert_last(this->attributes, entry); + } + tokens->destroy(tokens); + } + enumerator->destroy(enumerator); +} + +METHOD(attr_provider_t, reload, void, + private_attr_provider_t *this) +{ + this->lock->write_lock(this->lock); + + this->attributes->destroy_function(this->attributes, (void*)attribute_destroy); + this->attributes = linked_list_create(); + + load_entries(this); + + DBG1(DBG_CFG, "loaded %d entr%s for attr plugin configuration", + this->attributes->get_count(this->attributes), + this->attributes->get_count(this->attributes) == 1 ? "y" : "ies"); + + this->lock->unlock(this->lock); +} + +/* + * see header file + */ +attr_provider_t *attr_provider_create(database_t *db) +{ + private_attr_provider_t *this; + + INIT(this, + .public = { + .provider = { + .acquire_address = (void*)return_null, + .release_address = (void*)return_false, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .reload = _reload, + .destroy = _destroy, + }, + .attributes = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + load_entries(this); + + return &this->public; +} diff --git a/src/libcharon/plugins/attr/attr_provider.h b/src/libcharon/plugins/attr/attr_provider.h new file mode 100644 index 000000000..17db30408 --- /dev/null +++ b/src/libcharon/plugins/attr/attr_provider.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup attr_provider attr_provider + * @{ @ingroup attr + */ + +#ifndef ATTR_PROVIDER_H_ +#define ATTR_PROVIDER_H_ + +#include <attributes/attribute_provider.h> + +typedef struct attr_provider_t attr_provider_t; + +/** + * Provide configuration attributes through static strongswan.conf definition. + */ +struct attr_provider_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Reload configuration from strongswan.conf. + */ + void (*reload)(attr_provider_t *this); + + /** + * Destroy a attr_provider instance. + */ + void (*destroy)(attr_provider_t *this); +}; + +/** + * Create a attr_provider instance. + */ +attr_provider_t *attr_provider_create(); + +#endif /** ATTR_PROVIDER @}*/ diff --git a/src/libcharon/plugins/attr_sql/Makefile.am b/src/libcharon/plugins/attr_sql/Makefile.am new file mode 100644 index 000000000..366c902f7 --- /dev/null +++ b/src/libcharon/plugins/attr_sql/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-attr-sql.la +else +plugin_LTLIBRARIES = libstrongswan-attr-sql.la +endif + +libstrongswan_attr_sql_la_SOURCES = \ + attr_sql_plugin.h attr_sql_plugin.c \ + attr_sql_provider.h attr_sql_provider.c + +libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/attr_sql/Makefile.in index 1aca319c7..8f1b3c0ff 100644 --- a/src/libcharon/plugins/unit_tester/Makefile.in +++ b/src/libcharon/plugins/attr_sql/Makefile.in @@ -78,7 +78,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -subdir = src/libcharon/plugins/unit_tester +subdir = src/libcharon/plugins/attr_sql DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -127,25 +127,22 @@ am__uninstall_files_from_dir = { \ } am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) -libstrongswan_unit_tester_la_LIBADD = -am__dirstamp = $(am__leading_dot)dirstamp -am_libstrongswan_unit_tester_la_OBJECTS = unit_tester.lo \ - tests/test_auth_info.lo tests/test_curl.lo tests/test_mysql.lo \ - tests/test_sqlite.lo tests/test_cert.lo tests/test_med_db.lo \ - tests/test_pool.lo tests/test_agent.lo -libstrongswan_unit_tester_la_OBJECTS = \ - $(am_libstrongswan_unit_tester_la_OBJECTS) +libstrongswan_attr_sql_la_LIBADD = +am_libstrongswan_attr_sql_la_OBJECTS = attr_sql_plugin.lo \ + attr_sql_provider.lo +libstrongswan_attr_sql_la_OBJECTS = \ + $(am_libstrongswan_attr_sql_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -libstrongswan_unit_tester_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ +libstrongswan_attr_sql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_unit_tester_la_LDFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_attr_sql_la_LDFLAGS) \ $(LDFLAGS) -o $@ -@MONOLITHIC_FALSE@am_libstrongswan_unit_tester_la_rpath = -rpath \ +@MONOLITHIC_FALSE@am_libstrongswan_attr_sql_la_rpath = -rpath \ @MONOLITHIC_FALSE@ $(plugindir) -@MONOLITHIC_TRUE@am_libstrongswan_unit_tester_la_rpath = +@MONOLITHIC_TRUE@am_libstrongswan_attr_sql_la_rpath = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -180,8 +177,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libstrongswan_unit_tester_la_SOURCES) -DIST_SOURCES = $(libstrongswan_unit_tester_la_SOURCES) +SOURCES = $(libstrongswan_attr_sql_la_SOURCES) +DIST_SOURCES = $(libstrongswan_attr_sql_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -232,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -292,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -369,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ @@ -435,20 +437,13 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(PLUGIN_CFLAGS) -@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-unit-tester.la -@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-unit-tester.la -libstrongswan_unit_tester_la_SOURCES = \ - unit_tester.c unit_tester.h tests.h \ - tests/test_auth_info.c \ - tests/test_curl.c \ - tests/test_mysql.c \ - tests/test_sqlite.c \ - tests/test_cert.c \ - tests/test_med_db.c \ - tests/test_pool.c \ - tests/test_agent.c - -libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-attr-sql.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-attr-sql.la +libstrongswan_attr_sql_la_SOURCES = \ + attr_sql_plugin.h attr_sql_plugin.c \ + attr_sql_provider.h attr_sql_provider.c + +libstrongswan_attr_sql_la_LDFLAGS = -module -avoid-version all: all-am .SUFFIXES: @@ -462,9 +457,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/unit_tester/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/attr_sql/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/libcharon/plugins/unit_tester/Makefile + $(AUTOMAKE) --gnu src/libcharon/plugins/attr_sql/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -529,49 +524,18 @@ clean-pluginLTLIBRARIES: echo rm -f $${locs}; \ rm -f $${locs}; \ } -tests/$(am__dirstamp): - @$(MKDIR_P) tests - @: > tests/$(am__dirstamp) -tests/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) tests/$(DEPDIR) - @: > tests/$(DEPDIR)/$(am__dirstamp) -tests/test_auth_info.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_curl.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_mysql.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_sqlite.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_cert.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_med_db.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_pool.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/test_agent.lo: tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) - -libstrongswan-unit-tester.la: $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_DEPENDENCIES) $(EXTRA_libstrongswan_unit_tester_la_DEPENDENCIES) - $(AM_V_CCLD)$(libstrongswan_unit_tester_la_LINK) $(am_libstrongswan_unit_tester_la_rpath) $(libstrongswan_unit_tester_la_OBJECTS) $(libstrongswan_unit_tester_la_LIBADD) $(LIBS) + +libstrongswan-attr-sql.la: $(libstrongswan_attr_sql_la_OBJECTS) $(libstrongswan_attr_sql_la_DEPENDENCIES) $(EXTRA_libstrongswan_attr_sql_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_attr_sql_la_LINK) $(am_libstrongswan_attr_sql_la_rpath) $(libstrongswan_attr_sql_la_OBJECTS) $(libstrongswan_attr_sql_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) - -rm -f tests/*.$(OBJEXT) - -rm -f tests/*.lo distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unit_tester.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_agent.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_auth_info.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_cert.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_curl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_med_db.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_mysql.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_pool.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test_sqlite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_sql_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr_sql_provider.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -602,7 +566,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs - -rm -rf tests/.libs tests/_libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique @@ -719,8 +682,6 @@ 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) - -rm -f tests/$(DEPDIR)/$(am__dirstamp) - -rm -f tests/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -731,7 +692,7 @@ clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) tests/$(DEPDIR) + -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -777,7 +738,7 @@ install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) tests/$(DEPDIR) + -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/libcharon/plugins/attr_sql/attr_sql_plugin.c b/src/libcharon/plugins/attr_sql/attr_sql_plugin.c new file mode 100644 index 000000000..908877514 --- /dev/null +++ b/src/libcharon/plugins/attr_sql/attr_sql_plugin.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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 <daemon.h> +#include <utils/debug.h> +#include <plugins/plugin_feature.h> + +#include "attr_sql_plugin.h" +#include "attr_sql_provider.h" + +typedef struct private_attr_sql_plugin_t private_attr_sql_plugin_t; + +/** + * private data of attr_sql plugin + */ +struct private_attr_sql_plugin_t { + + /** + * implements plugin interface + */ + attr_sql_plugin_t public; + + /** + * database connection instance + */ + database_t *db; + + /** + * configuration attributes + */ + attr_sql_provider_t *attribute; +}; + +METHOD(plugin_t, get_name, char*, + private_attr_sql_plugin_t *this) +{ + return "attr-sql"; +} + +/** + * Connect to database + */ +static bool open_database(private_attr_sql_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + char *uri; + + uri = lib->settings->get_str(lib->settings, + "%s.plugins.attr-sql.database", NULL, lib->ns); + if (!uri) + { + DBG1(DBG_CFG, "attr-sql plugin: database URI not set"); + return FALSE; + } + + this->db = lib->db->create(lib->db, uri); + if (!this->db) + { + DBG1(DBG_CFG, "attr-sql plugin failed to connect to database"); + return FALSE; + } + this->attribute = attr_sql_provider_create(this->db); + charon->attributes->add_provider(charon->attributes, + &this->attribute->provider); + } + else + { + charon->attributes->remove_provider(charon->attributes, + &this->attribute->provider); + this->attribute->destroy(this->attribute); + this->db->destroy(this->db); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_attr_sql_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)open_database, NULL), + PLUGIN_PROVIDE(CUSTOM, "attr-sql"), + PLUGIN_DEPENDS(DATABASE, DB_ANY), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_attr_sql_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *attr_sql_plugin_create() +{ + private_attr_sql_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + lib->settings->add_fallback(lib->settings, "%s.plugins.attr-sql", + "libhydra.plugins.attr-sql", lib->ns); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/unit_tester/unit_tester.h b/src/libcharon/plugins/attr_sql/attr_sql_plugin.h index 08784f6f4..b6b04ccc0 100644 --- a/src/libcharon/plugins/unit_tester/unit_tester.h +++ b/src/libcharon/plugins/attr_sql/attr_sql_plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,31 +14,29 @@ */ /** - * @defgroup unit_tester unit_tester - * @{ @ingroup cplugins + * @defgroup attr_sql attr_sql + * @ingroup cplugins + * + * @defgroup attr_sql_plugin attr_sql_plugin + * @{ @ingroup attr_sql */ -#ifndef UNIT_TESTER_H_ -#define UNIT_TESTER_H_ +#ifndef ATTR_SQL_PLUGIN_H_ +#define ATTR_SQL_PLUGIN_H_ #include <plugins/plugin.h> -typedef struct unit_tester_t unit_tester_t; +typedef struct attr_sql_plugin_t attr_sql_plugin_t; /** - * Unit testing plugin. - * - * The unit testing plugin runs tests on plugin initialization. Tests are - * defined in tests.h using the DEFINE_TEST macro. Implementation of the - * tests is done in the tests folder. Each test has uses a function which - * returns TRUE for success or FALSE for failure. + * SQL database attribute configuration plugin */ -struct unit_tester_t { +struct attr_sql_plugin_t { /** - * Implements the plugin interface. + * implements plugin interface */ plugin_t plugin; }; -#endif /** UNIT_TESTER_H_ @}*/ +#endif /** ATTR_SQL_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/attr_sql/attr_sql_provider.c b/src/libcharon/plugins/attr_sql/attr_sql_provider.c new file mode 100644 index 000000000..c2410705d --- /dev/null +++ b/src/libcharon/plugins/attr_sql/attr_sql_provider.c @@ -0,0 +1,478 @@ +/* + * 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 <time.h> + +#include <utils/debug.h> +#include <library.h> + +#include "attr_sql_provider.h" + +typedef struct private_attr_sql_provider_t private_attr_sql_provider_t; + +/** + * private data of attr_sql_provider + */ +struct private_attr_sql_provider_t { + + /** + * public functions + */ + attr_sql_provider_t public; + + /** + * database connection + */ + database_t *db; + + /** + * whether to record lease history in lease table + */ + bool history; +}; + +/** + * lookup/insert an identity + */ +static u_int get_identity(private_attr_sql_provider_t *this, ike_sa_t *ike_sa) +{ + identification_t *id; + enumerator_t *e; + u_int row; + + id = ike_sa->get_other_eap_id(ike_sa); + + this->db->transaction(this->db, TRUE); + /* look for peer identity in the identities table */ + e = this->db->query(this->db, + "SELECT id FROM identities WHERE type = ? AND data = ?", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), + DB_UINT); + if (e && e->enumerate(e, &row)) + { + e->destroy(e); + this->db->commit(this->db); + return row; + } + DESTROY_IF(e); + /* not found, insert new one */ + if (this->db->execute(this->db, &row, + "INSERT INTO identities (type, data) VALUES (?, ?)", + DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) == 1) + { + this->db->commit(this->db); + return row; + } + this->db->rollback(this->db); + return 0; +} + +/** + * Lookup an attribute pool by name + */ +static u_int get_attr_pool(private_attr_sql_provider_t *this, char *name) +{ + enumerator_t *e; + u_int row = 0; + + e = this->db->query(this->db, + "SELECT id FROM attribute_pools WHERE name = ?", + DB_TEXT, name, DB_UINT); + if (e) + { + e->enumerate(e, &row); + } + DESTROY_IF(e); + + return row; +} + +/** + * Lookup pool by name and address family + */ +static u_int get_pool(private_attr_sql_provider_t *this, char *name, int family, + u_int *timeout) +{ + enumerator_t *e; + chunk_t start; + u_int pool; + + e = this->db->query(this->db, + "SELECT id, start, timeout FROM pools WHERE name = ?", + DB_TEXT, name, DB_UINT, DB_BLOB, DB_UINT); + if (e && e->enumerate(e, &pool, &start, timeout)) + { + if ((family == AF_INET && start.len == 4) || + (family == AF_INET6 && start.len == 16)) + { + e->destroy(e); + return pool; + } + } + DESTROY_IF(e); + return 0; +} + +/** + * Look up an existing lease + */ +static host_t* check_lease(private_attr_sql_provider_t *this, char *name, + u_int pool, u_int identity) +{ + while (TRUE) + { + u_int id; + chunk_t address; + enumerator_t *e; + time_t now = time(NULL); + + e = this->db->query(this->db, + "SELECT id, address FROM addresses " + "WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1", + DB_UINT, pool, DB_UINT, identity, DB_UINT, DB_BLOB); + if (!e || !e->enumerate(e, &id, &address)) + { + DESTROY_IF(e); + break; + } + address = chunk_clonea(address); + e->destroy(e); + + if (this->db->execute(this->db, NULL, + "UPDATE addresses SET acquired = ?, released = 0 " + "WHERE id = ? AND identity = ? AND released != 0", + DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0) + { + host_t *host; + + host = host_create_from_chunk(AF_UNSPEC, address, 0); + if (host) + { + DBG1(DBG_CFG, "acquired existing lease for address %H in" + " pool '%s'", host, name); + return host; + } + } + } + return NULL; +} + +/** + * We check for unallocated addresses or expired leases. First we select an + * address as a candidate, but double check later on if it is still available + * during the update operation. This allows us to work without locking. + */ +static host_t* get_lease(private_attr_sql_provider_t *this, char *name, + u_int pool, u_int timeout, u_int identity) +{ + while (TRUE) + { + u_int id; + chunk_t address; + enumerator_t *e; + time_t now = time(NULL); + int hits; + + if (timeout) + { + /* check for an expired lease */ + e = this->db->query(this->db, + "SELECT id, address FROM addresses " + "WHERE pool = ? AND released != 0 AND released < ? LIMIT 1", + DB_UINT, pool, DB_UINT, now - timeout, DB_UINT, DB_BLOB); + } + else + { + /* with static leases, check for an unallocated address */ + e = this->db->query(this->db, + "SELECT id, address FROM addresses " + "WHERE pool = ? AND identity = 0 LIMIT 1", + DB_UINT, pool, DB_UINT, DB_BLOB); + + } + + if (!e || !e->enumerate(e, &id, &address)) + { + DESTROY_IF(e); + break; + } + address = chunk_clonea(address); + e->destroy(e); + + if (timeout) + { + hits = this->db->execute(this->db, NULL, + "UPDATE addresses SET " + "acquired = ?, released = 0, identity = ? " + "WHERE id = ? AND released != 0 AND released < ?", + DB_UINT, now, DB_UINT, identity, + DB_UINT, id, DB_UINT, now - timeout); + } + else + { + hits = this->db->execute(this->db, NULL, + "UPDATE addresses SET " + "acquired = ?, released = 0, identity = ? " + "WHERE id = ? AND identity = 0", + DB_UINT, now, DB_UINT, identity, DB_UINT, id); + } + if (hits > 0) + { + host_t *host; + + host = host_create_from_chunk(AF_UNSPEC, address, 0); + if (host) + { + DBG1(DBG_CFG, "acquired new lease for address %H in pool '%s'", + host, name); + return host; + } + } + } + DBG1(DBG_CFG, "no available address found in pool '%s'", name); + return NULL; +} + +METHOD(attribute_provider_t, acquire_address, host_t*, + private_attr_sql_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, + host_t *requested) +{ + enumerator_t *enumerator; + host_t *address = NULL; + u_int identity, pool, timeout; + char *name; + int family; + + identity = get_identity(this, ike_sa); + if (identity) + { + family = requested->get_family(requested); + /* check for an existing lease in all pools */ + enumerator = pools->create_enumerator(pools); + while (enumerator->enumerate(enumerator, &name)) + { + pool = get_pool(this, name, family, &timeout); + if (pool) + { + address = check_lease(this, name, pool, identity); + if (address) + { + break; + } + } + } + enumerator->destroy(enumerator); + + if (!address) + { + /* get an unallocated address or expired lease */ + enumerator = pools->create_enumerator(pools); + while (enumerator->enumerate(enumerator, &name)) + { + pool = get_pool(this, name, family, &timeout); + if (pool) + { + address = get_lease(this, name, pool, timeout, identity); + if (address) + { + break; + } + } + } + enumerator->destroy(enumerator); + } + } + return address; +} + +METHOD(attribute_provider_t, release_address, bool, + private_attr_sql_provider_t *this, linked_list_t *pools, host_t *address, + ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + u_int pool, timeout; + time_t now = time(NULL); + bool found = FALSE; + char *name; + int family; + + family = address->get_family(address); + enumerator = pools->create_enumerator(pools); + while (enumerator->enumerate(enumerator, &name)) + { + pool = get_pool(this, name, family, &timeout); + if (!pool) + { + continue; + } + if (this->db->execute(this->db, NULL, + "UPDATE addresses SET released = ? WHERE " + "pool = ? AND address = ?", DB_UINT, time(NULL), + DB_UINT, pool, DB_BLOB, address->get_address(address)) > 0) + { + if (this->history) + { + this->db->execute(this->db, NULL, + "INSERT INTO leases (address, identity, acquired, released)" + " SELECT id, identity, acquired, ? FROM addresses " + " WHERE pool = ? AND address = ?", + DB_UINT, now, DB_UINT, pool, + DB_BLOB, address->get_address(address)); + } + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + +METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, + private_attr_sql_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, + linked_list_t *vips) +{ + enumerator_t *attr_enumerator = NULL; + + if (vips->get_count(vips)) + { + enumerator_t *pool_enumerator; + u_int count; + char *name; + + /* in a first step check for attributes that match name and id */ + if (ike_sa) + { + u_int identity = get_identity(this, ike_sa); + + pool_enumerator = pools->create_enumerator(pools); + while (pool_enumerator->enumerate(pool_enumerator, &name)) + { + u_int attr_pool = get_attr_pool(this, name); + if (!attr_pool) + { + continue; + } + + attr_enumerator = this->db->query(this->db, + "SELECT count(*) FROM attributes " + "WHERE pool = ? AND identity = ?", + DB_UINT, attr_pool, DB_UINT, identity, DB_UINT); + + if (attr_enumerator && + attr_enumerator->enumerate(attr_enumerator, &count) && + count != 0) + { + attr_enumerator->destroy(attr_enumerator); + attr_enumerator = this->db->query(this->db, + "SELECT type, value FROM attributes " + "WHERE pool = ? AND identity = ?", DB_UINT, + attr_pool, DB_UINT, identity, DB_INT, DB_BLOB); + break; + } + DESTROY_IF(attr_enumerator); + attr_enumerator = NULL; + } + pool_enumerator->destroy(pool_enumerator); + } + + /* in a second step check for attributes that match name */ + if (!attr_enumerator) + { + pool_enumerator = pools->create_enumerator(pools); + while (pool_enumerator->enumerate(pool_enumerator, &name)) + { + u_int attr_pool = get_attr_pool(this, name); + if (!attr_pool) + { + continue; + } + + attr_enumerator = this->db->query(this->db, + "SELECT count(*) FROM attributes " + "WHERE pool = ? AND identity = 0", + DB_UINT, attr_pool, DB_UINT); + + if (attr_enumerator && + attr_enumerator->enumerate(attr_enumerator, &count) && + count != 0) + { + attr_enumerator->destroy(attr_enumerator); + attr_enumerator = this->db->query(this->db, + "SELECT type, value FROM attributes " + "WHERE pool = ? AND identity = 0", + DB_UINT, attr_pool, DB_INT, DB_BLOB); + break; + } + DESTROY_IF(attr_enumerator); + attr_enumerator = NULL; + } + pool_enumerator->destroy(pool_enumerator); + } + + /* lastly try to find global attributes */ + if (!attr_enumerator) + { + attr_enumerator = this->db->query(this->db, + "SELECT type, value FROM attributes " + "WHERE pool = 0 AND identity = 0", + DB_INT, DB_BLOB); + } + } + + return (attr_enumerator ? attr_enumerator : enumerator_create_empty()); +} + +METHOD(attr_sql_provider_t, destroy, void, + private_attr_sql_provider_t *this) +{ + free(this); +} + +/* + * see header file + */ +attr_sql_provider_t *attr_sql_provider_create(database_t *db) +{ + private_attr_sql_provider_t *this; + time_t now = time(NULL); + + INIT(this, + .public = { + .provider = { + .acquire_address = _acquire_address, + .release_address = _release_address, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + .db = db, + .history = lib->settings->get_bool(lib->settings, + "%s.plugins.attr-sql.lease_history", TRUE, lib->ns), + ); + + /* close any "online" leases in the case we crashed */ + if (this->history) + { + this->db->execute(this->db, NULL, + "INSERT INTO leases (address, identity, acquired, released)" + " SELECT id, identity, acquired, ? FROM addresses " + " WHERE released = 0", DB_UINT, now); + } + this->db->execute(this->db, NULL, + "UPDATE addresses SET released = ? WHERE released = 0", + DB_UINT, now); + return &this->public; +} diff --git a/src/libcharon/plugins/attr_sql/attr_sql_provider.h b/src/libcharon/plugins/attr_sql/attr_sql_provider.h new file mode 100644 index 000000000..a9b037bf5 --- /dev/null +++ b/src/libcharon/plugins/attr_sql/attr_sql_provider.h @@ -0,0 +1,50 @@ +/* + * 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 attr_sql_provider attr_sql_provider + * @{ @ingroup attr_sql + */ + +#ifndef ATTR_SQL_PROVIDER_H_ +#define ATTR_SQL_PROVIDER_H_ + +#include <attributes/attribute_provider.h> +#include <database/database.h> + +typedef struct attr_sql_provider_t attr_sql_provider_t; + +/** + * SQL database based IKEv2 cfg attribute provider. + */ +struct attr_sql_provider_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Destroy a attr_sql_provider instance. + */ + void (*destroy)(attr_sql_provider_t *this); +}; + +/** + * Create a attr_sql_provider instance. + */ +attr_sql_provider_t *attr_sql_provider_create(database_t *db); + +#endif /** ATTR_SQL_PROVIDER_H_ @}*/ diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in index 08101d51d..f946d73c1 100644 --- a/src/libcharon/plugins/certexpire/Makefile.in +++ b/src/libcharon/plugins/certexpire/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/connmark/Makefile.am b/src/libcharon/plugins/connmark/Makefile.am new file mode 100644 index 000000000..cc4d0ec8d --- /dev/null +++ b/src/libcharon/plugins/connmark/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) $(libiptc_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-connmark.la +else +plugin_LTLIBRARIES = libstrongswan-connmark.la +endif + +libstrongswan_connmark_la_SOURCES = \ + connmark_listener.h connmark_listener.c \ + connmark_plugin.h connmark_plugin.c + +libstrongswan_connmark_la_LDFLAGS = -module -avoid-version +libstrongswan_connmark_la_LIBADD = $(libiptc_LIBS) diff --git a/src/libcharon/plugins/connmark/Makefile.in b/src/libcharon/plugins/connmark/Makefile.in new file mode 100644 index 000000000..65f53fde9 --- /dev/null +++ b/src/libcharon/plugins/connmark/Makefile.in @@ -0,0 +1,782 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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/connmark +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +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__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_connmark_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_connmark_la_OBJECTS = connmark_listener.lo \ + connmark_plugin.lo +libstrongswan_connmark_la_OBJECTS = \ + $(am_libstrongswan_connmark_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_connmark_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_connmark_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_connmark_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_connmark_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_connmark_la_SOURCES) +DIST_SOURCES = $(libstrongswan_connmark_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) $(libiptc_CFLAGS) + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-connmark.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-connmark.la +libstrongswan_connmark_la_SOURCES = \ + connmark_listener.h connmark_listener.c \ + connmark_plugin.h connmark_plugin.c + +libstrongswan_connmark_la_LDFLAGS = -module -avoid-version +libstrongswan_connmark_la_LIBADD = $(libiptc_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/connmark/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/connmark/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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @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 " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + 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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-connmark.la: $(libstrongswan_connmark_la_OBJECTS) $(libstrongswan_connmark_la_DEPENDENCIES) $(EXTRA_libstrongswan_connmark_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_connmark_la_LINK) $(am_libstrongswan_connmark_la_rpath) $(libstrongswan_connmark_la_OBJECTS) $(libstrongswan_connmark_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connmark_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connmark_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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 TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am 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 tags-am 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/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c new file mode 100644 index 000000000..23df690e8 --- /dev/null +++ b/src/libcharon/plugins/connmark/connmark_listener.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 "connmark_listener.h" + +#include <daemon.h> + +#include <errno.h> +#include <libiptc/libiptc.h> +#include <linux/netfilter/xt_esp.h> +#include <linux/netfilter/xt_tcpudp.h> +#include <linux/netfilter/xt_MARK.h> +#include <linux/netfilter/xt_policy.h> +#include <linux/netfilter/xt_CONNMARK.h> + + +typedef struct private_connmark_listener_t private_connmark_listener_t; + +/** + * Private data of an connmark_listener_t object. + */ +struct private_connmark_listener_t { + + /** + * Public connmark_listener_t interface. + */ + connmark_listener_t public; +}; + +/** + * Convert an (IPv4) traffic selector to an address and mask + */ +static bool ts2in(traffic_selector_t *ts, + struct in_addr *addr, struct in_addr *mask) +{ + u_int8_t bits; + host_t *net; + + if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE && + ts->to_subnet(ts, &net, &bits)) + { + memcpy(&addr->s_addr, net->get_address(net).ptr, 4); + net->destroy(net); + mask->s_addr = htonl(0xffffffffU << (32 - bits)); + return TRUE; + } + return FALSE; +} + +/** + * Convert an (IPv4) host to an address with mask + */ +static bool host2in(host_t *host, struct in_addr *addr, struct in_addr *mask) +{ + if (host->get_family(host) == AF_INET) + { + memcpy(&addr->s_addr, host->get_address(host).ptr, 4); + mask->s_addr = ~0; + return TRUE; + } + return FALSE; +} + +/** + * Add or remove a rule to/from the specified chain + */ +static bool manage_rule(struct iptc_handle *ipth, const char *chain, + bool add, struct ipt_entry *e) +{ + if (add) + { + if (!iptc_insert_entry(chain, e, 0, ipth)) + { + DBG1(DBG_CFG, "appending %s rule failed: %s", + chain, iptc_strerror(errno)); + return FALSE; + } + } + else + { + if (!iptc_delete_entry(chain, e, "", ipth)) + { + DBG1(DBG_CFG, "deleting %s rule failed: %s", + chain, iptc_strerror(errno)); + return FALSE; + } + } + return TRUE; +} + +/** + * Add rule marking UDP-encapsulated ESP packets to match the correct policy + */ +static bool manage_pre_esp_in_udp(private_connmark_listener_t *this, + struct iptc_handle *ipth, bool add, + u_int mark, u_int32_t spi, + host_t *dst, host_t *src) +{ + struct { + struct ipt_entry e; + struct ipt_entry_match m; + struct xt_udp udp; + struct ipt_entry_target t; + struct xt_mark_tginfo2 tm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + + sizeof(ipt.udp)), + .next_offset = sizeof(ipt), + .ip = { + .proto = IPPROTO_UDP, + }, + }, + .m = { + .u = { + .user = { + .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)), + .name = "udp", + }, + }, + }, + .udp = { + .spts = { src->get_port(src), src->get_port(src) }, + .dpts = { dst->get_port(dst), dst->get_port(dst) }, + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), + .name = "MARK", + .revision = 2, + }, + }, + }, + .tm = { + .mark = mark, + .mask = ~0, + }, + }; + + if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "PREROUTING", add, &ipt.e); +} + +/** + * Add rule marking non-encapsulated ESP packets to match the correct policy + */ +static bool manage_pre_esp(private_connmark_listener_t *this, + struct iptc_handle *ipth, bool add, + u_int mark, u_int32_t spi, + host_t *dst, host_t *src) +{ + struct { + struct ipt_entry e; + struct ipt_entry_match m; + struct xt_esp esp; + struct ipt_entry_target t; + struct xt_mark_tginfo2 tm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + + sizeof(ipt.esp)), + .next_offset = sizeof(ipt), + .ip = { + .proto = IPPROTO_ESP, + }, + }, + .m = { + .u = { + .user = { + .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)), + .name = "esp", + }, + }, + }, + .esp = { + .spis = { htonl(spi), htonl(spi) }, + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), + .name = "MARK", + .revision = 2, + }, + }, + }, + .tm = { + .mark = mark, + .mask = ~0, + }, + }; + + if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "PREROUTING", add, &ipt.e); +} + +/** + * Add rule marking ESP packets to match the correct policy + */ +static bool manage_pre(private_connmark_listener_t *this, + struct iptc_handle *ipth, bool add, + u_int mark, u_int32_t spi, bool encap, + host_t *dst, host_t *src) +{ + if (encap) + { + return manage_pre_esp_in_udp(this, ipth, add, mark, spi, dst, src); + } + return manage_pre_esp(this, ipth, add, mark, spi, dst, src); +} + +/** + * Add inbound rule applying CONNMARK to matching traffic + */ +static bool manage_in(private_connmark_listener_t *this, + struct iptc_handle *ipth, bool add, + u_int mark, u_int32_t spi, + traffic_selector_t *dst, traffic_selector_t *src) +{ + struct { + struct ipt_entry e; + struct ipt_entry_match m; + struct xt_policy_info p; + struct ipt_entry_target t; + struct xt_connmark_tginfo1 cm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + + sizeof(ipt.p)), + .next_offset = sizeof(ipt), + }, + .m = { + .u = { + .user = { + .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)), + .name = "policy", + }, + }, + }, + .p = { + .pol = { + { + .spi = spi, + .match.spi = 1, + }, + }, + .len = 1, + .flags = XT_POLICY_MATCH_IN, + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)), + .name = "CONNMARK", + .revision = 1, + }, + }, + }, + .cm = { + .ctmark = mark, + .ctmask = ~0, + .nfmask = ~0, + .mode = XT_CONNMARK_SET, + }, + }; + + if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "INPUT", add, &ipt.e); +} + +/** + * Add outbund rule restoring CONNMARK on matching traffic + */ +static bool manage_out(private_connmark_listener_t *this, + struct iptc_handle *ipth, bool add, + traffic_selector_t *dst, traffic_selector_t *src) +{ + struct { + struct ipt_entry e; + struct ipt_entry_target t; + struct xt_connmark_tginfo1 cm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e)), + .next_offset = sizeof(ipt), + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)), + .name = "CONNMARK", + .revision = 1, + }, + }, + }, + .cm = { + .ctmask = ~0, + .nfmask = ~0, + .mode = XT_CONNMARK_RESTORE, + }, + }; + + if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "OUTPUT", add, &ipt.e); +} + +/** + * Initialize iptables handle, log error + */ +static struct iptc_handle* init_handle() +{ + struct iptc_handle *ipth; + + ipth = iptc_init("mangle"); + if (ipth) + { + return ipth; + } + DBG1(DBG_CFG, "initializing iptables failed: %s", iptc_strerror(errno)); + return NULL; +} + +/** + * Commit iptables rules, log error + */ +static bool commit_handle(struct iptc_handle *ipth) +{ + if (iptc_commit(ipth)) + { + return TRUE; + } + DBG1(DBG_CFG, "forecast iptables commit failed: %s", iptc_strerror(errno)); + return FALSE; +} + +/** + * Add/Remove policies for a CHILD_SA using a iptables handle + */ +static bool manage_policies(private_connmark_listener_t *this, + struct iptc_handle *ipth, host_t *dst, host_t *src, + bool encap, child_sa_t *child_sa, bool add) +{ + traffic_selector_t *local, *remote; + enumerator_t *enumerator; + u_int32_t spi; + u_int mark; + bool done = TRUE; + + spi = child_sa->get_spi(child_sa, TRUE); + mark = child_sa->get_mark(child_sa, TRUE).value; + + enumerator = child_sa->create_policy_enumerator(child_sa); + while (enumerator->enumerate(enumerator, &local, &remote)) + { + if (!manage_pre(this, ipth, add, mark, spi, encap, dst, src) || + !manage_in(this, ipth, add, mark, spi, local, remote) || + !manage_out(this, ipth, add, remote, local)) + { + done = FALSE; + break; + } + } + enumerator->destroy(enumerator); + + return done; +} + +/** + * Check if rules should be installed for given CHILD_SA + */ +static bool handle_sa(child_sa_t *child_sa) +{ + return child_sa->get_mark(child_sa, TRUE).value && + child_sa->get_mark(child_sa, FALSE).value && + child_sa->get_mode(child_sa) == MODE_TRANSPORT && + child_sa->get_protocol(child_sa) == PROTO_ESP; +} + +METHOD(listener_t, child_updown, bool, + private_connmark_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool up) +{ + struct iptc_handle *ipth; + host_t *dst, *src; + bool encap; + + dst = ike_sa->get_my_host(ike_sa); + src = ike_sa->get_other_host(ike_sa); + encap = child_sa->has_encap(child_sa); + + if (handle_sa(child_sa)) + { + ipth = init_handle(); + if (ipth) + { + if (manage_policies(this, ipth, dst, src, encap, child_sa, up)) + { + commit_handle(ipth); + } + iptc_free(ipth); + } + } + return TRUE; +} + +METHOD(listener_t, child_rekey, bool, + private_connmark_listener_t *this, ike_sa_t *ike_sa, + child_sa_t *old, child_sa_t *new) +{ + struct iptc_handle *ipth; + host_t *dst, *src; + bool oldencap, newencap; + + dst = ike_sa->get_my_host(ike_sa); + src = ike_sa->get_other_host(ike_sa); + oldencap = old->has_encap(old); + newencap = new->has_encap(new); + + if (handle_sa(old)) + { + ipth = init_handle(); + if (ipth) + { + if (manage_policies(this, ipth, dst, src, oldencap, old, FALSE) && + manage_policies(this, ipth, dst, src, newencap, new, TRUE)) + { + commit_handle(ipth); + } + iptc_free(ipth); + } + } + return TRUE; +} + +METHOD(listener_t, ike_update, bool, + private_connmark_listener_t *this, ike_sa_t *ike_sa, + bool local, host_t *new) +{ + struct iptc_handle *ipth; + enumerator_t *enumerator; + child_sa_t *child_sa; + host_t *dst, *src; + bool oldencap, newencap; + + if (local) + { + dst = new; + src = ike_sa->get_other_host(ike_sa); + } + else + { + dst = ike_sa->get_my_host(ike_sa); + src = new; + } + /* during ike_update(), has_encap() on the CHILD_SA has not yet been + * updated, but shows the old state. */ + newencap = ike_sa->has_condition(ike_sa, COND_NAT_ANY); + + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, &child_sa)) + { + if (handle_sa(child_sa)) + { + oldencap = child_sa->has_encap(child_sa); + ipth = init_handle(); + if (ipth) + { + if (manage_policies(this, ipth, dst, src, oldencap, + child_sa, FALSE) && + manage_policies(this, ipth, dst, src, newencap, + child_sa, TRUE)) + { + commit_handle(ipth); + } + iptc_free(ipth); + } + } + } + enumerator->destroy(enumerator); + + return TRUE; +} + +METHOD(connmark_listener_t, destroy, void, + private_connmark_listener_t *this) +{ + free(this); +} + +/** + * See header + */ +connmark_listener_t *connmark_listener_create() +{ + private_connmark_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_update = _ike_update, + .child_updown = _child_updown, + .child_rekey = _child_rekey, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/connmark/connmark_listener.h b/src/libcharon/plugins/connmark/connmark_listener.h new file mode 100644 index 000000000..2d4098fb6 --- /dev/null +++ b/src/libcharon/plugins/connmark/connmark_listener.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 connmark_listener connmark_listener + * @{ @ingroup connmark + */ + +#ifndef CONNMARK_LISTENER_H_ +#define CONNMARK_LISTENER_H_ + +#include <bus/listeners/listener.h> + +typedef struct connmark_listener_t connmark_listener_t; + +/** + * Listener to install Netfilter rules + */ +struct connmark_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a connmark_listener_t. + */ + void (*destroy)(connmark_listener_t *this); +}; + +/** + * Create a connmark_listener instance. + */ +connmark_listener_t *connmark_listener_create(); + +#endif /** CONNMARK_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/connmark/connmark_plugin.c b/src/libcharon/plugins/connmark/connmark_plugin.c new file mode 100644 index 000000000..3f276f93e --- /dev/null +++ b/src/libcharon/plugins/connmark/connmark_plugin.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 "connmark_plugin.h" +#include "connmark_listener.h" + +#include <daemon.h> + +typedef struct private_connmark_plugin_t private_connmark_plugin_t; + +/** + * private data of connmark plugin + */ +struct private_connmark_plugin_t { + + /** + * implements plugin interface + */ + connmark_plugin_t public; + + /** + * Listener installing netfilter rules + */ + connmark_listener_t *listener; +}; + +METHOD(plugin_t, get_name, char*, + private_connmark_plugin_t *this) +{ + return "connmark"; +} + +/** + * Register listener + */ +static bool plugin_cb(private_connmark_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_connmark_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "connmark"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_connmark_plugin_t *this) +{ + this->listener->destroy(this->listener); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *connmark_plugin_create() +{ + private_connmark_plugin_t *this; + + if (!lib->caps->keep(lib->caps, CAP_NET_ADMIN)) + { + DBG1(DBG_NET, "connmark plugin requires CAP_NET_ADMIN capability"); + return NULL; + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .listener = connmark_listener_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/connmark/connmark_plugin.h b/src/libcharon/plugins/connmark/connmark_plugin.h new file mode 100644 index 000000000..5b4ccebbe --- /dev/null +++ b/src/libcharon/plugins/connmark/connmark_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 connmark connmark + * @ingroup cplugins + * + * @defgroup connmark_plugin connmark_plugin + * @{ @ingroup connmark + */ + +#ifndef CONNMARK_PLUGIN_H_ +#define CONNMARK_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct connmark_plugin_t connmark_plugin_t; + +/** + * Plugin using marks to select return path SA based on conntrack. + */ +struct connmark_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** CONNMARK_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in index 679d2dae6..dff80c37f 100644 --- a/src/libcharon/plugins/coupling/Makefile.in +++ b/src/libcharon/plugins/coupling/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in index 768c2b32b..1e84f04e2 100644 --- a/src/libcharon/plugins/dhcp/Makefile.in +++ b/src/libcharon/plugins/dhcp/Makefile.in @@ -227,6 +227,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -287,10 +288,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -364,6 +367,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.c b/src/libcharon/plugins/dhcp/dhcp_plugin.c index c36c60d28..642e28afc 100644 --- a/src/libcharon/plugins/dhcp/dhcp_plugin.c +++ b/src/libcharon/plugins/dhcp/dhcp_plugin.c @@ -18,7 +18,6 @@ #include "dhcp_plugin.h" -#include <hydra.h> #include <daemon.h> #include <plugins/plugin_feature.h> @@ -69,13 +68,13 @@ static bool plugin_cb(private_dhcp_plugin_t *this, return FALSE; } this->provider = dhcp_provider_create(this->socket); - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->add_provider(charon->attributes, + &this->provider->provider); } else { - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->remove_provider(charon->attributes, + &this->provider->provider); this->provider->destroy(this->provider); this->socket->destroy(this->socket); } diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c index f5325b566..f0681b1da 100644 --- a/src/libcharon/plugins/dhcp/dhcp_provider.c +++ b/src/libcharon/plugins/dhcp/dhcp_provider.c @@ -66,10 +66,11 @@ static uintptr_t hash_transaction(dhcp_transaction_t *transaction) METHOD(attribute_provider_t, acquire_address, host_t*, private_dhcp_provider_t *this, linked_list_t *pools, - identification_t *id, host_t *requested) + ike_sa_t *ike_sa, host_t *requested) { dhcp_transaction_t *transaction, *old; enumerator_t *enumerator; + identification_t *id; char *pool; host_t *vip = NULL; @@ -77,6 +78,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*, { return NULL; } + id = ike_sa->get_other_eap_id(ike_sa); enumerator = pools->create_enumerator(pools); while (enumerator->enumerate(enumerator, &pool)) { @@ -104,10 +106,11 @@ METHOD(attribute_provider_t, acquire_address, host_t*, METHOD(attribute_provider_t, release_address, bool, private_dhcp_provider_t *this, linked_list_t *pools, - host_t *address, identification_t *id) + host_t *address, ike_sa_t *ike_sa) { dhcp_transaction_t *transaction; enumerator_t *enumerator; + identification_t *id; bool found = FALSE; char *pool; @@ -115,6 +118,7 @@ METHOD(attribute_provider_t, release_address, bool, { return FALSE; } + id = ike_sa->get_other_eap_id(ike_sa); enumerator = pools->create_enumerator(pools); while (enumerator->enumerate(enumerator, &pool)) { @@ -139,11 +143,12 @@ METHOD(attribute_provider_t, release_address, bool, } METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, - private_dhcp_provider_t *this, linked_list_t *pools, identification_t *id, + private_dhcp_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, linked_list_t *vips) { dhcp_transaction_t *transaction = NULL; enumerator_t *enumerator; + identification_t *id; host_t *vip; if (pools->find_first(pools, (linked_list_match_t)streq, @@ -152,6 +157,7 @@ METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, return NULL; } + id = ike_sa->get_other_eap_id(ike_sa); this->mutex->lock(this->mutex); enumerator = vips->create_enumerator(vips); while (enumerator->enumerate(enumerator, &vip)) diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in index 3484e08a3..ed873b316 100644 --- a/src/libcharon/plugins/dnscert/Makefile.in +++ b/src/libcharon/plugins/dnscert/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in index 381d7a119..41862cb2a 100644 --- a/src/libcharon/plugins/duplicheck/Makefile.in +++ b/src/libcharon/plugins/duplicheck/Makefile.in @@ -236,6 +236,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -296,10 +297,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -373,6 +376,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in index 3b0f8763c..dacddfb87 100644 --- a/src/libcharon/plugins/eap_aka/Makefile.in +++ b/src/libcharon/plugins/eap_aka/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in index 839a379ea..3c26b8511 100644 --- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in +++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in index fdbad6234..402c7cadc 100644 --- a/src/libcharon/plugins/eap_dynamic/Makefile.in +++ b/src/libcharon/plugins/eap_dynamic/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in index 9675104da..2279b2514 100644 --- a/src/libcharon/plugins/eap_gtc/Makefile.in +++ b/src/libcharon/plugins/eap_gtc/Makefile.in @@ -228,6 +228,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -288,10 +289,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -365,6 +368,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in index 0610b5859..30d2c88d1 100644 --- a/src/libcharon/plugins/eap_identity/Makefile.in +++ b/src/libcharon/plugins/eap_identity/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in index 38c9d0b7c..14616c214 100644 --- a/src/libcharon/plugins/eap_md5/Makefile.in +++ b/src/libcharon/plugins/eap_md5/Makefile.in @@ -228,6 +228,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -288,10 +289,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -365,6 +368,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in index f5dfd6814..78dfd29e3 100644 --- a/src/libcharon/plugins/eap_mschapv2/Makefile.in +++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in index 5ccd58158..2f0d65d6d 100644 --- a/src/libcharon/plugins/eap_peap/Makefile.in +++ b/src/libcharon/plugins/eap_peap/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in index 04cc422f5..47534372b 100644 --- a/src/libcharon/plugins/eap_radius/Makefile.in +++ b/src/libcharon/plugins/eap_radius/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c index 31c96d229..ac4ecfc86 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c @@ -99,7 +99,7 @@ typedef struct { /** IKE_SA identifier this entry is stored under */ ike_sa_id_t *id; /** RADIUS accounting session ID */ - char sid[16]; + char sid[24]; /** number of sent/received octets/packets */ struct { u_int64_t sent; diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c index 1a48c07e5..6a4a0384e 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c @@ -26,7 +26,7 @@ #include <radius_client.h> #include <radius_config.h> -#include <hydra.h> +#include <daemon.h> #include <threading/rwlock.h> #include <processing/jobs/callback_job.h> #include <processing/jobs/delete_ike_sa_job.h> @@ -149,19 +149,26 @@ static void load_configs(private_eap_radius_plugin_t *this) continue; } nas_identifier = lib->settings->get_str(lib->settings, - "%s.plugins.eap-radius.servers.%s.nas_identifier", "strongSwan", + "%s.plugins.eap-radius.servers.%s.nas_identifier", + lib->settings->get_str(lib->settings, + "%s.plugins.eap-radius.nas_identifier", "strongSwan", + lib->ns), lib->ns, section); auth_port = lib->settings->get_int(lib->settings, "%s.plugins.eap-radius.servers.%s.auth_port", lib->settings->get_int(lib->settings, "%s.plugins.eap-radius.servers.%s.port", - AUTH_PORT, lib->ns, section), + lib->settings->get_int(lib->settings, + "%s.plugins.eap-radius.port", AUTH_PORT, lib->ns), + lib->ns, section), lib->ns, section); acct_port = lib->settings->get_int(lib->settings, "%s.plugins.eap-radius.servers.%s.acct_port", ACCT_PORT, lib->ns, section); sockets = lib->settings->get_int(lib->settings, - "%s.plugins.eap-radius.servers.%s.sockets", 1, + "%s.plugins.eap-radius.servers.%s.sockets", + lib->settings->get_int(lib->settings, + "%s.plugins.eap-radius.sockets", 1, lib->ns), lib->ns, section); preference = lib->settings->get_int(lib->settings, "%s.plugins.eap-radius.servers.%s.preference", 0, @@ -211,13 +218,13 @@ static bool plugin_cb(private_eap_radius_plugin_t *this, { charon->bus->add_listener(charon->bus, &this->forward->listener); } - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->add_provider(charon->attributes, + &this->provider->provider); } else { - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->remove_provider(charon->attributes, + &this->provider->provider); if (this->forward) { charon->bus->remove_listener(charon->bus, &this->forward->listener); diff --git a/src/libcharon/plugins/eap_radius/eap_radius_provider.c b/src/libcharon/plugins/eap_radius/eap_radius_provider.c index 7c794616b..0cf723711 100644 --- a/src/libcharon/plugins/eap_radius/eap_radius_provider.c +++ b/src/libcharon/plugins/eap_radius/eap_radius_provider.c @@ -311,19 +311,13 @@ METHOD(listener_t, ike_rekey, bool, METHOD(attribute_provider_t, acquire_address, host_t*, private_eap_radius_provider_t *this, linked_list_t *pools, - identification_t *id, host_t *requested) + ike_sa_t *ike_sa, host_t *requested) { enumerator_t *enumerator; host_t *addr = NULL; - ike_sa_t *ike_sa; uintptr_t sa; char *name; - ike_sa = charon->bus->get_sa(charon->bus); - if (!ike_sa) - { - return NULL; - } sa = ike_sa->get_unique_id(ike_sa); enumerator = pools->create_enumerator(pools); @@ -348,19 +342,13 @@ METHOD(attribute_provider_t, acquire_address, host_t*, METHOD(attribute_provider_t, release_address, bool, private_eap_radius_provider_t *this, linked_list_t *pools, host_t *address, - identification_t *id) + ike_sa_t *ike_sa) { enumerator_t *enumerator; host_t *found = NULL; - ike_sa_t *ike_sa; uintptr_t sa; char *name; - ike_sa = charon->bus->get_sa(charon->bus); - if (!ike_sa) - { - return FALSE; - } sa = ike_sa->get_unique_id(ike_sa); enumerator = pools->create_enumerator(pools); @@ -428,18 +416,12 @@ METHOD(enumerator_t, attribute_destroy, void, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_eap_radius_provider_t *this, linked_list_t *pools, - identification_t *id, linked_list_t *vips) + ike_sa_t *ike_sa, linked_list_t *vips) { attribute_enumerator_t *enumerator; attr_t *attr; - ike_sa_t *ike_sa; uintptr_t sa; - ike_sa = charon->bus->get_sa(charon->bus); - if (!ike_sa) - { - return NULL; - } sa = ike_sa->get_unique_id(ike_sa); INIT(enumerator, diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in index 6a00ea74d..251eeeeba 100644 --- a/src/libcharon/plugins/eap_sim/Makefile.in +++ b/src/libcharon/plugins/eap_sim/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in index 7a08f4e0e..bffcbc0df 100644 --- a/src/libcharon/plugins/eap_sim_file/Makefile.in +++ b/src/libcharon/plugins/eap_sim_file/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in index a1ec7adc1..78682ce37 100644 --- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in +++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in @@ -232,6 +232,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -292,10 +293,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -369,6 +372,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in index bf99ab095..2a6be5fd9 100644 --- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in @@ -232,6 +232,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -292,10 +293,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -369,6 +372,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in index ce4602365..de504d4cd 100644 --- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in index 0c0b7fd52..de3508a07 100644 --- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in +++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in index 25696f524..d4219b876 100644 --- a/src/libcharon/plugins/eap_tls/Makefile.in +++ b/src/libcharon/plugins/eap_tls/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_tls/eap_tls.c b/src/libcharon/plugins/eap_tls/eap_tls.c index dffbaf266..bc01ba5df 100644 --- a/src/libcharon/plugins/eap_tls/eap_tls.c +++ b/src/libcharon/plugins/eap_tls/eap_tls.c @@ -109,6 +109,12 @@ METHOD(eap_method_t, is_mutual, bool, return TRUE; } +METHOD(eap_method_t, get_auth, auth_cfg_t*, + private_eap_tls_t *this) +{ + return this->tls_eap->get_auth(this->tls_eap); +} + METHOD(eap_method_t, destroy, void, private_eap_tls_t *this) { @@ -138,6 +144,7 @@ static eap_tls_t *eap_tls_create(identification_t *server, .get_msk = _get_msk, .get_identifier = _get_identifier, .set_identifier = _set_identifier, + .get_auth = _get_auth, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in index 2d5d65875..6c34ed098 100644 --- a/src/libcharon/plugins/eap_tnc/Makefile.in +++ b/src/libcharon/plugins/eap_tnc/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index 62d23d064..f70f47ef6 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Andreas Steffen + * Copyright (C) 2010-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -256,6 +256,8 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, private_eap_tnc_t *this; int max_msg_count; char* protocol; + ike_sa_t *ike_sa; + host_t *server_ip, *peer_ip; tnccs_t *tnccs; tnccs_type_t tnccs_type; @@ -302,8 +304,29 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, free(this); return NULL; } + + /* Determine IP addresses of server and peer */ + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + DBG1(DBG_TNC, "%N constructor did not find IKE_SA", + eap_type_names, type); + free(this); + return NULL; + } + if (is_server) + { + server_ip = ike_sa->get_my_host(ike_sa); + peer_ip = ike_sa->get_other_host(ike_sa); + } + else + { + peer_ip = ike_sa->get_my_host(ike_sa); + server_ip = ike_sa->get_other_host(ike_sa); + } + tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type, - is_server, server, peer, + is_server, server, peer, server_ip, peer_ip, (type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0, is_server ? enforce_recommendation : NULL); if (!tnccs) diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in index 38c7632ac..0babf1766 100644 --- a/src/libcharon/plugins/eap_ttls/Makefile.in +++ b/src/libcharon/plugins/eap_ttls/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls.c b/src/libcharon/plugins/eap_ttls/eap_ttls.c index 703cd3f29..c99d47f8d 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls.c @@ -111,6 +111,12 @@ METHOD(eap_method_t, is_mutual, bool, return TRUE; } +METHOD(eap_method_t, get_auth, auth_cfg_t*, + private_eap_ttls_t *this) +{ + return this->tls_eap->get_auth(this->tls_eap); +} + METHOD(eap_method_t, destroy, void, private_eap_ttls_t *this) { @@ -141,6 +147,7 @@ static eap_ttls_t *eap_ttls_create(identification_t *server, .get_identifier = _get_identifier, .set_identifier = _set_identifier, .get_msk = _get_msk, + .get_auth = _get_auth, .destroy = _destroy, }, }, diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in index d9fa454ca..0a07aa7a3 100644 --- a/src/libcharon/plugins/error_notify/Makefile.in +++ b/src/libcharon/plugins/error_notify/Makefile.in @@ -237,6 +237,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -297,10 +298,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -374,6 +377,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in index a1b47dd33..d23e680aa 100644 --- a/src/libcharon/plugins/ext_auth/Makefile.in +++ b/src/libcharon/plugins/ext_auth/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in index 2bfd38ba1..318400fc9 100644 --- a/src/libcharon/plugins/farp/Makefile.in +++ b/src/libcharon/plugins/farp/Makefile.in @@ -227,6 +227,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -287,10 +288,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -364,6 +367,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/forecast/Makefile.am b/src/libcharon/plugins/forecast/Makefile.am new file mode 100644 index 000000000..ce573135d --- /dev/null +++ b/src/libcharon/plugins/forecast/Makefile.am @@ -0,0 +1,21 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) $(libiptc_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-forecast.la +else +plugin_LTLIBRARIES = libstrongswan-forecast.la +endif + +libstrongswan_forecast_la_SOURCES = \ + forecast_listener.h forecast_listener.c \ + forecast_forwarder.h forecast_forwarder.c \ + forecast_plugin.h forecast_plugin.c + +libstrongswan_forecast_la_LDFLAGS = -module -avoid-version +libstrongswan_forecast_la_LIBADD = $(libiptc_LIBS) diff --git a/src/libcharon/plugins/forecast/Makefile.in b/src/libcharon/plugins/forecast/Makefile.in new file mode 100644 index 000000000..7b190ca25 --- /dev/null +++ b/src/libcharon/plugins/forecast/Makefile.in @@ -0,0 +1,784 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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/forecast +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +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__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(plugindir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES) +am__DEPENDENCIES_1 = +libstrongswan_forecast_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libstrongswan_forecast_la_OBJECTS = forecast_listener.lo \ + forecast_forwarder.lo forecast_plugin.lo +libstrongswan_forecast_la_OBJECTS = \ + $(am_libstrongswan_forecast_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_forecast_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_forecast_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MONOLITHIC_FALSE@am_libstrongswan_forecast_la_rpath = -rpath \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_forecast_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_forecast_la_SOURCES) +DIST_SOURCES = $(libstrongswan_forecast_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) $(libiptc_CFLAGS) + +@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-forecast.la +@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-forecast.la +libstrongswan_forecast_la_SOURCES = \ + forecast_listener.h forecast_listener.c \ + forecast_forwarder.h forecast_forwarder.c \ + forecast_plugin.h forecast_plugin.c + +libstrongswan_forecast_la_LDFLAGS = -module -avoid-version +libstrongswan_forecast_la_LIBADD = $(libiptc_LIBS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/forecast/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/forecast/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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @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 " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + 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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-forecast.la: $(libstrongswan_forecast_la_OBJECTS) $(libstrongswan_forecast_la_DEPENDENCIES) $(EXTRA_libstrongswan_forecast_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_forecast_la_LINK) $(am_libstrongswan_forecast_la_rpath) $(libstrongswan_forecast_la_OBJECTS) $(libstrongswan_forecast_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forecast_forwarder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forecast_listener.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forecast_plugin.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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 TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am 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 tags-am 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/forecast/forecast_forwarder.c b/src/libcharon/plugins/forecast/forecast_forwarder.c new file mode 100644 index 000000000..07a3d4953 --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_forwarder.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 "forecast_forwarder.h" + +#include <errno.h> +#include <unistd.h> +#include <netinet/ip.h> +#include <netinet/udp.h> +#include <linux/socket.h> +#include <netinet/if_ether.h> +#include <linux/if_packet.h> +#include <linux/filter.h> +#include <sys/ioctl.h> +#include <ifaddrs.h> +#include <net/if.h> + +#include <hydra.h> +#include <daemon.h> +#include <threading/thread.h> +#include <processing/jobs/callback_job.h> + +#define BOOTP_SERVER_PORT 67 +#define BOOTP_CLIENT_PORT 68 + +typedef struct private_forecast_forwarder_t private_forecast_forwarder_t; +typedef struct private_kernel_listener_t private_kernel_listener_t; + +/** + * Private data of registered kernel listener + */ +struct private_kernel_listener_t { + + /** + * Implements kernel_listener_t + */ + kernel_listener_t listener; + + /** + * Listener that knows active addresses + */ + forecast_listener_t *fc; + + /** + * current broadcast address of internal network + */ + u_int32_t broadcast; + + /** + * LAN interface index + */ + int ifindex; + + /** + * Packet socket + */ + int pkt; + + /** + * RAW socket + */ + int raw; +}; + +/** + * Private data of an forecast_forwarder_t object. + */ +struct private_forecast_forwarder_t { + + /** + * Public forecast_forwarder_t interface. + */ + forecast_forwarder_t public; + + /** + * Public kernel_listener_t interface. + */ + private_kernel_listener_t kernel; +}; + +/** + * Send a broadcast/multicast packet to a network + */ +static void send_net(private_forecast_forwarder_t *this, + struct sockaddr_ll *addr, void *buf, size_t len) +{ + if (sendto(this->kernel.pkt, buf, len, 0, + (struct sockaddr*)addr, sizeof(*addr)) != len) + { + DBG1(DBG_NET, "forecast send_net() failed: %s", strerror(errno)); + } +} + +/** + * Send a broadcast/multicast packet to a peer + */ +static void send_peer(private_forecast_forwarder_t *this, u_int32_t dst, + void *buf, size_t len, int mark) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = dst, + }; + + if (setsockopt(this->kernel.raw, SOL_SOCKET, SO_MARK, + &mark, sizeof(mark)) != 0) + { + DBG1(DBG_NET, "forecast setting SO_MARK failed: %s", strerror(errno)); + } + if (sendto(this->kernel.raw, buf, len, 0, + (struct sockaddr*)&addr, sizeof(addr)) != len) + { + DBG1(DBG_NET, "forecast send_peer() failed: %s", strerror(errno)); + } +} + +/** + * Check if an IP packet is BOOTP/DHCP + */ +static bool is_bootp(void *buf, size_t len) +{ + struct __attribute__((__packed__)) { + struct iphdr ip; + struct udphdr udp; + } *pkt = buf; + + if (len > sizeof(*pkt)) + { + if (ntohs(pkt->udp.source) == BOOTP_CLIENT_PORT && + ntohs(pkt->udp.dest) == BOOTP_SERVER_PORT) + { + return TRUE; + } + if (ntohs(pkt->udp.source) == BOOTP_SERVER_PORT && + ntohs(pkt->udp.dest) == BOOTP_CLIENT_PORT) + { + return TRUE; + } + } + return FALSE; +} + +/** + * Broadcast/Multicast receiver + */ +static bool receive_casts(private_forecast_forwarder_t *this) +{ + struct __attribute__((packed)) { + struct iphdr hdr; + char data[2048]; + } buf; + char *type; + ssize_t len; + u_int mark, origin = 0; + host_t *src, *dst; + traffic_selector_t *ts; + enumerator_t *enumerator; + struct sockaddr_ll addr; + socklen_t alen = sizeof(addr); + bool reinject; + + len = recvfrom(this->kernel.pkt, &buf, sizeof(buf), MSG_DONTWAIT, + (struct sockaddr*)&addr, &alen); + if (len < 0) + { + if (errno != EAGAIN && errno != EWOULDBLOCK) + { + DBG1(DBG_NET, "receiving from forecast socket failed: %s", + strerror(errno)); + } + return TRUE; + } + else if (len < sizeof(struct iphdr)) + { + DBG1(DBG_NET, "received short forecast packet: %zd bytes", len); + return TRUE; + } + if (is_bootp(&buf, len)) + { /* don't forward DHCP broadcasts */ + return TRUE; + } + + src = host_create_from_chunk(AF_INET, chunk_from_thing(buf.hdr.saddr), 0); + dst = host_create_from_chunk(AF_INET, chunk_from_thing(buf.hdr.daddr), 0); + + /* create valid broadcast/multicast MAC to send out */ + if (IN_MULTICAST(ntohl(buf.hdr.daddr))) + { + type = "multi"; + ETHER_MAP_IP_MULTICAST(&buf.hdr.daddr, addr.sll_addr); + } + else + { + type = "broad"; + memset(&addr.sll_addr, 0xFF, sizeof(addr.sll_addr)); + } + DBG2(DBG_NET, "forecast intercepted packet: %H to %H", src, dst); + + /* find mark of originating tunnel */ + enumerator = this->kernel.fc->create_enumerator(this->kernel.fc, FALSE); + while (enumerator->enumerate(enumerator, &ts, &mark, &reinject)) + { + if (ts->includes(ts, src)) + { + origin = mark; + break; + } + } + enumerator->destroy(enumerator); + + /* send packet over all tunnels, but not the packets origin */ + enumerator = this->kernel.fc->create_enumerator(this->kernel.fc, FALSE); + while (enumerator->enumerate(enumerator, &ts, &mark, &reinject)) + { + if (ts->includes(ts, dst)) + { + if ((reinject && origin != mark) || origin == 0) + { + DBG2(DBG_NET, "forwarding a %H %scast from %H to peer %R (%u)", + dst, type, src, ts, mark); + send_peer(this, buf.hdr.daddr, &buf, len, mark); + } + } + } + enumerator->destroy(enumerator); + + if (origin) + { + /* forward broadcast/multicast from client to network */ + DBG2(DBG_NET, "forwarding a %H %scast from peer %H to internal network", + dst, type, src); + addr.sll_ifindex = this->kernel.ifindex; + send_net(this, &addr, &buf, len); + } + + dst->destroy(dst); + src->destroy(src); + + return TRUE; +} + +/** + * Join a multicast group + */ +static void join_group(private_kernel_listener_t *this, char *group, + struct sockaddr *addr) +{ + struct sockaddr_in *in; + struct ip_mreqn mreq; + host_t *host; + + host = host_create_from_string(group, 0); + if (host) + { + memset(&mreq, 0, sizeof(mreq)); + memcpy(&mreq.imr_multiaddr.s_addr, host->get_address(host).ptr, 4); + if (addr->sa_family == AF_INET) + { + in = (struct sockaddr_in*)addr; + memcpy(&mreq.imr_address, &in->sin_addr.s_addr, + sizeof(in->sin_addr.s_addr)); + } + mreq.imr_ifindex = this->ifindex; + if (setsockopt(this->raw, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mreq, sizeof(mreq)) == -1) + { + if (errno != EADDRINUSE) + { + DBG1(DBG_NET, "forecast multicast join to %s failed: %s", + group, strerror(errno)); + } + } + else + { + DBG2(DBG_NET, "forwarding multicast group %s", group); + } + host->destroy(host); + } +} + +/** + * (Re-)Join all multicast groups we want to forward + */ +static void join_groups(private_kernel_listener_t *this, struct sockaddr *addr) +{ + enumerator_t *enumerator; + char *groups, *group; + static char *def = + "224.0.0.1," /* host multicast */ + "224.0.0.22," /* IGMP */ + "224.0.0.251," /* mDNS */ + "224.0.0.252," /* LLMNR */ + "239.255.255.250"; /* SSDP/WS-discovery */ + + groups = lib->settings->get_str(lib->settings, + "%s.plugins.forecast.groups", def, lib->ns); + DBG1(DBG_CFG, "joining forecast multicast groups: %s", groups); + enumerator = enumerator_create_token(groups, ",", " "); + while (enumerator->enumerate(enumerator, &group)) + { + join_group(this, group, addr); + } + enumerator->destroy(enumerator); +} + +/** + * Attach the socket filter to the socket + */ +static bool attach_filter(int fd, u_int32_t broadcast) +{ + struct sock_filter filter_code[] = { + /* destination address: is ... */ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct iphdr, daddr)), + /* broadcast, as received from the local network */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ntohl(broadcast), 4, 0), + /* broadcast, as Win7 sends them */ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xFFFFFFFF, 3, 0), + /* any multicast, 224.0.0.0/4 */ + BPF_STMT(BPF_ALU+BPF_AND+BPF_K, 0xF0000000), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xE0000000, 1, 0), + BPF_STMT(BPF_RET+BPF_K, 0), + BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0), + BPF_STMT(BPF_RET+BPF_A, 0), + }; + struct sock_fprog filter = { + sizeof(filter_code) / sizeof(struct sock_filter), + filter_code, + }; + + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, + &filter, sizeof(filter)) < 0) + { + DBG1(DBG_NET, "installing forecast PACKET socket filter failed: %s", + strerror(errno)); + return FALSE; + } + return TRUE; +} + +/** + * Get the interface index of an interface name + */ +static int get_ifindex(private_kernel_listener_t *this, char *ifname) +{ + struct ifreq ifr = {}; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if (ioctl(this->raw, SIOCGIFINDEX, &ifr) == 0) + { + return ifr.ifr_ifindex; + } + return 0; +} + +/** + * Set up the interface for broad/multicast forwarding + */ +static void setup_interface(private_kernel_listener_t *this) +{ + struct ifaddrs *addrs, *current; + struct sockaddr_in *in; + host_t *host; + char *name; + + name = lib->settings->get_str(lib->settings, + "%s.plugins.forecast.interface", NULL, lib->ns); + if (getifaddrs(&addrs) == 0) + { + for (current = addrs; current; current = current->ifa_next) + { + if (name && !streq(name, current->ifa_name)) + { + continue; + } + if (current->ifa_flags & IFF_BROADCAST && + current->ifa_broadaddr && + current->ifa_broadaddr->sa_family == AF_INET) + { + DBG1(DBG_NET, "using forecast interface %s", current->ifa_name); + this->ifindex = get_ifindex(this, current->ifa_name); + in = (struct sockaddr_in*)current->ifa_broadaddr; + attach_filter(this->pkt, in->sin_addr.s_addr); + join_groups(this, current->ifa_addr); + host = host_create_from_sockaddr(current->ifa_broadaddr); + if (host) + { + this->fc->set_broadcast(this->fc, host); + host->destroy(host); + } + break; + } + } + } + freeifaddrs(addrs); +} + +METHOD(kernel_listener_t, roam, bool, + private_kernel_listener_t *this, bool address) +{ + if (address) + { + setup_interface(this); + } + return TRUE; +} + +METHOD(forecast_forwarder_t, destroy, void, + private_forecast_forwarder_t *this) +{ + if (this->kernel.raw != -1) + { + close(this->kernel.raw); + } + if (this->kernel.pkt != -1) + { + lib->watcher->remove(lib->watcher, this->kernel.pkt); + close(this->kernel.pkt); + } + hydra->kernel_interface->remove_listener(hydra->kernel_interface, + &this->kernel.listener); + free(this); +} + +/** + * See header + */ +forecast_forwarder_t *forecast_forwarder_create(forecast_listener_t *listener) +{ + private_forecast_forwarder_t *this; + int on = 1; + + INIT(this, + .public = { + .destroy = _destroy, + }, + .kernel = { + .listener = { + .roam = _roam, + }, + .raw = -1, + .pkt = -1, + .fc = listener, + }, + ); + + this->kernel.pkt = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + if (this->kernel.pkt == -1) + { + DBG1(DBG_NET, "opening PACKET socket failed: %s", strerror(errno)); + destroy(this); + return NULL; + } + this->kernel.raw = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + if (this->kernel.raw == -1) + { + DBG1(DBG_NET, "opening RAW socket failed: %s", strerror(errno)); + destroy(this); + return NULL; + } + if (setsockopt(this->kernel.raw, IPPROTO_IP, IP_HDRINCL, + &on, sizeof(on)) == -1) + { + DBG1(DBG_NET, "forecast socket HDRINCL failed: %s", strerror(errno)); + destroy(this); + return NULL; + } + if (setsockopt(this->kernel.raw, SOL_SOCKET, SO_BROADCAST, + &on, sizeof(on)) == -1) + { + DBG1(DBG_NET, "forecast socket BROADCAST failed: %s", strerror(errno)); + destroy(this); + return NULL; + } + + setup_interface(&this->kernel); + + hydra->kernel_interface->add_listener(hydra->kernel_interface, + &this->kernel.listener); + + lib->watcher->add(lib->watcher, this->kernel.pkt, WATCHER_READ, + (watcher_cb_t)receive_casts, this); + + return &this->public; +} diff --git a/src/libcharon/plugins/forecast/forecast_forwarder.h b/src/libcharon/plugins/forecast/forecast_forwarder.h new file mode 100644 index 000000000..14d107361 --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_forwarder.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 forecast_forwarder forecast_forwarder + * @{ @ingroup forecast + */ + +#ifndef FORECAST_FORWARDER_H_ +#define FORECAST_FORWARDER_H_ + +#include "forecast_listener.h" + +typedef struct forecast_forwarder_t forecast_forwarder_t; + +/** + * Broadcast/Multicast sniffer and forwarder. + */ +struct forecast_forwarder_t { + + /** + * Destroy a forecast_forwarder_t. + */ + void (*destroy)(forecast_forwarder_t *this); +}; + +/** + * Create a forecast_forwarder instance. + * + * @param listener listener to check for addresses to forward to + * @return forwarder instance + */ +forecast_forwarder_t *forecast_forwarder_create(forecast_listener_t *listener); + +#endif /** FORECAST_FORWARDER_H_ @}*/ diff --git a/src/libcharon/plugins/forecast/forecast_listener.c b/src/libcharon/plugins/forecast/forecast_listener.c new file mode 100644 index 000000000..63a8cb15b --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_listener.c @@ -0,0 +1,680 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 "forecast_listener.h" + +#include <errno.h> +#include <libiptc/libiptc.h> +#include <linux/netfilter/xt_MARK.h> +#include <linux/netfilter/xt_esp.h> + +#include <daemon.h> +#include <collections/array.h> +#include <collections/hashtable.h> +#include <threading/rwlock.h> + +typedef struct private_forecast_listener_t private_forecast_listener_t; + +/** + * Private data of an forecast_listener_t object. + */ +struct private_forecast_listener_t { + + /** + * Public forecast_listener_t interface. + */ + forecast_listener_t public; + + /** + * List of entries + */ + linked_list_t *entries; + + /** + * RWlock for IP list + */ + rwlock_t *lock; + + /** + * Configs we do reinjection + */ + char *reinject_configs; + + /** + * Broadcast address on LAN interface, network order + */ + u_int32_t broadcast; +}; + +/** + * Hashtable entry + */ +typedef struct { + /** local traffic selectors */ + array_t *lts; + /** remote traffic selectors */ + array_t *rts; + /** firewall mark used by CHILD_SA */ + u_int mark; + /** local IKE_SA endpoint */ + host_t *lhost; + /** remote IKE_SA endpoint */ + host_t *rhost; + /** inbound SPI */ + u_int32_t spi; + /** use UDP encapsulation */ + bool encap; + /** whether we should allow reencapsulation of IPsec received forecasts */ + bool reinject; + /** broadcast address used for that entry */ + u_int32_t broadcast; +} entry_t; + +/** + * Destroy an entry + */ +static void entry_destroy(entry_t *entry) +{ + if (entry) + { + entry->lhost->destroy(entry->lhost); + entry->rhost->destroy(entry->rhost); + array_destroy_offset(entry->lts, offsetof(traffic_selector_t, destroy)); + array_destroy_offset(entry->rts, offsetof(traffic_selector_t, destroy)); + free(entry); + } +} + +/** + * Convert an (IPv4) traffic selector to an address and mask + */ +static bool ts2in(traffic_selector_t *ts, + struct in_addr *addr, struct in_addr *mask) +{ + u_int8_t bits; + host_t *net; + + if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE && + ts->to_subnet(ts, &net, &bits)) + { + memcpy(&addr->s_addr, net->get_address(net).ptr, 4); + net->destroy(net); + mask->s_addr = htonl(0xffffffffU << (32 - bits)); + return TRUE; + } + return FALSE; +} + +/** + * Convert an (IPv4) host to an address with mask + */ +static bool host2in(host_t *host, struct in_addr *addr, struct in_addr *mask) +{ + if (host->get_family(host) == AF_INET) + { + memcpy(&addr->s_addr, host->get_address(host).ptr, 4); + mask->s_addr = ~0; + return TRUE; + } + return FALSE; +} + +/** + * Add or remove a rule to/from the specified chain + */ +static bool manage_rule(struct iptc_handle *ipth, const char *chain, + bool add, struct ipt_entry *e) +{ + if (add) + { + if (!iptc_insert_entry(chain, e, 0, ipth)) + { + DBG1(DBG_CFG, "appending %s rule failed: %s", + chain, iptc_strerror(errno)); + return FALSE; + } + } + else + { + if (!iptc_delete_entry(chain, e, "", ipth)) + { + DBG1(DBG_CFG, "deleting %s rule failed: %s", + chain, iptc_strerror(errno)); + return FALSE; + } + } + return TRUE; +} + +/** + * Add rule marking UDP-encapsulated ESP packets to match the correct policy + */ +static bool manage_pre_esp_in_udp(struct iptc_handle *ipth, + entry_t *entry, bool add) +{ + struct { + struct ipt_entry e; + struct ipt_entry_match m; + struct xt_udp udp; + struct ipt_entry_target t; + struct xt_mark_tginfo2 tm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + + sizeof(ipt.udp)), + .next_offset = sizeof(ipt), + .ip = { + .proto = IPPROTO_UDP, + }, + }, + .m = { + .u = { + .user = { + .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)), + .name = "udp", + }, + }, + }, + .udp = { + .spts = { + entry->rhost->get_port(entry->rhost), + entry->rhost->get_port(entry->lhost) + }, + .dpts = { + entry->lhost->get_port(entry->lhost), + entry->lhost->get_port(entry->lhost) + }, + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), + .name = "MARK", + .revision = 2, + }, + }, + }, + .tm = { + .mark = entry->mark, + .mask = ~0, + }, + }; + + if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "PREROUTING", add, &ipt.e); +} + +/** + * Add rule marking non-encapsulated ESP packets to match the correct policy + */ +static bool manage_pre_esp(struct iptc_handle *ipth, entry_t *entry, bool add) +{ + struct { + struct ipt_entry e; + struct ipt_entry_match m; + struct xt_esp esp; + struct ipt_entry_target t; + struct xt_mark_tginfo2 tm; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) + + sizeof(ipt.esp)), + .next_offset = sizeof(ipt), + .ip = { + .proto = IPPROTO_ESP, + }, + }, + .m = { + .u = { + .user = { + .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)), + .name = "esp", + }, + }, + }, + .esp = { + .spis = { htonl(entry->spi), htonl(entry->spi) }, + }, + .t = { + .u = { + .user = { + .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)), + .name = "MARK", + .revision = 2, + }, + }, + }, + .tm = { + .mark = entry->mark, + .mask = ~0, + }, + }; + + if (!host2in(entry->lhost, &ipt.e.ip.dst, &ipt.e.ip.dmsk) || + !host2in(entry->rhost, &ipt.e.ip.src, &ipt.e.ip.smsk)) + { + return FALSE; + } + return manage_rule(ipth, "PREROUTING", add, &ipt.e); +} + +/** + * Add rule marking ESP packets to match the correct policy + */ +static bool manage_pre(struct iptc_handle *ipth, entry_t *entry, bool add) +{ + if (entry->encap) + { + return manage_pre_esp_in_udp(ipth, entry, add); + } + return manage_pre_esp(ipth, entry, add); +} + +/** + * Add rule handling outbound traffic to use correct mark + */ +static bool manage_out(struct iptc_handle *ipth, entry_t *entry, bool add) +{ + struct { + struct ipt_entry e; + struct ipt_entry_target t; + struct xt_mark_tginfo2 m; + } ipt = { + .e = { + .target_offset = XT_ALIGN(sizeof(ipt.e)), + .next_offset = sizeof(ipt), + }, + .t = { + .u.user.target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.m)), + .u.user.name = "MARK", + .u.user.revision = 2, + }, + .m = { + .mark = entry->mark, + .mask = ~0, + }, + }; + enumerator_t *enumerator; + traffic_selector_t *ts; + + enumerator = array_create_enumerator(entry->rts); + while (enumerator->enumerate(enumerator, &ts)) + { + if (!ts2in(ts, &ipt.e.ip.dst, &ipt.e.ip.dmsk)) + { + continue; + } + if (ipt.e.ip.dst.s_addr == 0xffffffff || + ipt.e.ip.dst.s_addr == entry->broadcast || + memeq(&ipt.e.ip.dst.s_addr, "\xe0", 1)) + { + /* skip broadcast/multicast selectors, they are shared and the mark + * is set by the socket we use for reinjection */ + continue; + } + if (!manage_rule(ipth, "PREROUTING", add, &ipt.e) || + !manage_rule(ipth, "OUTPUT", add, &ipt.e)) + { + enumerator->destroy(enumerator); + return FALSE; + } + } + enumerator->destroy(enumerator); + + return TRUE; +} + +/** + * Check if config is whitelisted to reinject traffic + */ +static bool is_reinject_config(private_forecast_listener_t *this, char *name) +{ + enumerator_t *enumerator; + bool reinject = FALSE; + char *token; + + enumerator = enumerator_create_token(this->reinject_configs, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + if (streq(token, name)) + { + reinject = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return reinject; +} + +/** + * Add rules and entry for given CHILD_SA + */ +static bool add_entry(private_forecast_listener_t *this, + struct iptc_handle *ipth, host_t *lhost, host_t *rhost, + child_sa_t *child_sa, bool encap) +{ + enumerator_t *enumerator; + traffic_selector_t *ts; + entry_t *entry; + + INIT(entry, + .lts = array_create(0, 0), + .rts = array_create(0, 0), + .lhost = lhost->clone(lhost), + .rhost = rhost->clone(rhost), + .spi = child_sa->get_spi(child_sa, TRUE), + .encap = encap, + .mark = child_sa->get_mark(child_sa, TRUE).value, + .reinject = is_reinject_config(this, child_sa->get_name(child_sa)), + .broadcast = this->broadcast, + ); + + enumerator = child_sa->create_ts_enumerator(child_sa, TRUE); + while (enumerator->enumerate(enumerator, &ts)) + { + array_insert(entry->lts, ARRAY_TAIL, ts->clone(ts)); + } + enumerator->destroy(enumerator); + + enumerator = child_sa->create_ts_enumerator(child_sa, FALSE); + while (enumerator->enumerate(enumerator, &ts)) + { + array_insert(entry->rts, ARRAY_TAIL, ts->clone(ts)); + } + enumerator->destroy(enumerator); + + if (manage_pre(ipth, entry, TRUE) && + manage_out(ipth, entry, TRUE)) + { + this->lock->write_lock(this->lock); + this->entries->insert_last(this->entries, entry); + this->lock->unlock(this->lock); + return TRUE; + } + entry_destroy(entry); + return FALSE; +} + +/** + * Remove an entry and rules for a given mark + */ +static bool remove_entry(private_forecast_listener_t *this, + struct iptc_handle *ipth, child_sa_t *child_sa) +{ + enumerator_t *enumerator; + entry_t *entry; + bool done = FALSE; + + this->lock->write_lock(this->lock); + enumerator = this->entries->create_enumerator(this->entries); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->mark == child_sa->get_mark(child_sa, TRUE).value) + { + this->entries->remove_at(this->entries, enumerator); + if (manage_pre(ipth, entry, FALSE) && + manage_out(ipth, entry, FALSE)) + { + done = TRUE; + } + entry_destroy(entry); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + return done; +} + +/** + * Initialize iptables handle, log error + */ +static struct iptc_handle* init_handle() +{ + struct iptc_handle *ipth; + + ipth = iptc_init("mangle"); + if (ipth) + { + return ipth; + } + DBG1(DBG_CFG, "initializing iptables failed: %s", iptc_strerror(errno)); + return NULL; +} + +/** + * Commit iptables rules, log error + */ +static bool commit_handle(struct iptc_handle *ipth) +{ + if (iptc_commit(ipth)) + { + return TRUE; + } + DBG1(DBG_CFG, "forecast iptables commit failed: %s", iptc_strerror(errno)); + return FALSE; +} + +/** + * Check if we should handle the given CHILD_SA + */ +static bool handle_sa(child_sa_t *child_sa) +{ + return child_sa->get_mark(child_sa, TRUE).value && + child_sa->get_mark(child_sa, FALSE).value; +} + +METHOD(listener_t, child_updown, bool, + private_forecast_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, + bool up) +{ + struct iptc_handle *ipth; + host_t *lhost, *rhost; + bool encap; + + lhost = ike_sa->get_my_host(ike_sa); + rhost = ike_sa->get_other_host(ike_sa); + encap = child_sa->has_encap(child_sa); + + if (handle_sa(child_sa)) + { + ipth = init_handle(); + if (ipth) + { + if (up) + { + if (add_entry(this, ipth, lhost, rhost, child_sa, encap)) + { + commit_handle(ipth); + } + } + else + { + if (remove_entry(this, ipth, child_sa)) + { + commit_handle(ipth); + } + } + iptc_free(ipth); + } + } + return TRUE; +} + +METHOD(listener_t, child_rekey, bool, + private_forecast_listener_t *this, ike_sa_t *ike_sa, + child_sa_t *old, child_sa_t *new) +{ + struct iptc_handle *ipth;; + host_t *lhost, *rhost; + + lhost = ike_sa->get_my_host(ike_sa); + rhost = ike_sa->get_other_host(ike_sa); + + if (handle_sa(old)) + { + ipth = init_handle(); + if (ipth) + { + if (remove_entry(this, ipth, old) && + add_entry(this, ipth, lhost, rhost, new, new->has_encap(new))) + { + commit_handle(ipth); + } + iptc_free(ipth); + } + } + return TRUE; +} + +METHOD(listener_t, ike_update, bool, + private_forecast_listener_t *this, ike_sa_t *ike_sa, + bool local, host_t *new) +{ + struct iptc_handle *ipth; + enumerator_t *enumerator; + child_sa_t *child_sa; + host_t *lhost, *rhost; + bool encap; + + if (local) + { + lhost = new; + rhost = ike_sa->get_other_host(ike_sa); + } + else + { + lhost = ike_sa->get_my_host(ike_sa); + rhost = new; + } + /* during ike_update(), has_encap() on the CHILD_SA has not yet been + * updated, but shows the old state. */ + encap = ike_sa->has_condition(ike_sa, COND_NAT_ANY); + + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, &child_sa)) + { + if (handle_sa(child_sa)) + { + ipth = init_handle(); + if (ipth) + { + if (remove_entry(this, ipth, child_sa) && + add_entry(this, ipth, lhost, rhost, child_sa, encap)) + { + commit_handle(ipth); + } + iptc_free(ipth); + } + } + } + enumerator->destroy(enumerator); + + return TRUE; +} + +/** + * Filter to map entries to ts/mark + */ +static bool ts_filter(entry_t *entry, traffic_selector_t **ts, + traffic_selector_t **out, void *dummy, u_int32_t *mark, + void *dummy2, bool *reinject) +{ + *out = *ts; + *mark = entry->mark; + *reinject = entry->reinject; + return TRUE; +} + +/** + * Create inner enumerator over local traffic selectors + */ +static enumerator_t* create_inner_local(entry_t *entry, rwlock_t *lock) +{ + return enumerator_create_filter(array_create_enumerator(entry->lts), + (void*)ts_filter, entry, NULL); +} + +/** + * Create inner enumerator over remote traffic selectors + */ +static enumerator_t* create_inner_remote(entry_t *entry, rwlock_t *lock) +{ + return enumerator_create_filter(array_create_enumerator(entry->rts), + (void*)ts_filter, entry, NULL); +} + +METHOD(forecast_listener_t, create_enumerator, enumerator_t*, + private_forecast_listener_t *this, bool local) +{ + this->lock->read_lock(this->lock); + return enumerator_create_nested( + this->entries->create_enumerator(this->entries), + (void*)(local ? create_inner_local : create_inner_remote), + this->lock, (void*)this->lock->unlock); +} + +METHOD(forecast_listener_t, set_broadcast, void, + private_forecast_listener_t *this, host_t *bcast) +{ + if (bcast->get_family(bcast) == AF_INET) + { + struct sockaddr_in *in; + + in = (struct sockaddr_in*)bcast->get_sockaddr(bcast); + this->broadcast = in->sin_addr.s_addr; + } +} + +METHOD(forecast_listener_t, destroy, void, + private_forecast_listener_t *this) +{ + this->entries->destroy(this->entries); + this->lock->destroy(this->lock); + free(this); +} + +/** + * See header + */ +forecast_listener_t *forecast_listener_create() +{ + private_forecast_listener_t *this; + + INIT(this, + .public = { + .listener = { + .ike_update = _ike_update, + .child_updown = _child_updown, + .child_rekey = _child_rekey, + }, + .create_enumerator = _create_enumerator, + .set_broadcast = _set_broadcast, + .destroy = _destroy, + }, + .entries = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .reinject_configs = lib->settings->get_str(lib->settings, + "%s.plugins.forecast.reinject", "", lib->ns), + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/forecast/forecast_listener.h b/src/libcharon/plugins/forecast/forecast_listener.h new file mode 100644 index 000000000..49827ecb1 --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_listener.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 forecast_listener forecast_listener + * @{ @ingroup forecast + */ + +#ifndef FORECAST_LISTENER_H_ +#define FORECAST_LISTENER_H_ + +#include <bus/listeners/listener.h> + +typedef struct forecast_listener_t forecast_listener_t; + +/** + * Listener to register the set of IPs we forward received multi/broadcasts to. + */ +struct forecast_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Create an enumerator over active tunnels. + * + * The enumerator enumerates over local or remote traffic selectors, + * associated firewall marks and if decasulated packets should get + * reinjected into other tunnels. + * + * @param local TRUE to enumerate local, FALSE to enumerate remote TS + * @return enumerator over (traffic_selector_t*, u_int, bool) + */ + enumerator_t* (*create_enumerator)(forecast_listener_t *this, bool local); + + /** + * Set the broadcast address of the LAN interface. + * + * @param bcast broadcast address + */ + void (*set_broadcast)(forecast_listener_t *this, host_t *bcast); + + /** + * Destroy a forecast_listener_t. + */ + void (*destroy)(forecast_listener_t *this); +}; + +/** + * Create a forecast_listener instance. + */ +forecast_listener_t *forecast_listener_create(); + +#endif /** FORECAST_LISTENER_H_ @}*/ diff --git a/src/libcharon/plugins/forecast/forecast_plugin.c b/src/libcharon/plugins/forecast/forecast_plugin.c new file mode 100644 index 000000000..a129b76b2 --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_plugin.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 "forecast_plugin.h" +#include "forecast_listener.h" +#include "forecast_forwarder.h" + +#include <daemon.h> + +typedef struct private_forecast_plugin_t private_forecast_plugin_t; + +/** + * Private data of forecast plugin + */ +struct private_forecast_plugin_t { + + /** + * implements plugin interface + */ + forecast_plugin_t public; + + /** + * Listener registering active tunnels + */ + forecast_listener_t *listener; + + /** + * Broadcast/Multicast sniffer and forwarder + */ + forecast_forwarder_t *forwarder; +}; + +METHOD(plugin_t, get_name, char*, + private_forecast_plugin_t *this) +{ + return "forecast"; +} + +/** + * Register plugin features + */ +static bool register_forecast(private_forecast_plugin_t *this, + plugin_feature_t *feature, bool reg, void *data) +{ + if (reg) + { + this->forwarder = forecast_forwarder_create(this->listener); + if (!this->forwarder) + { + return FALSE; + } + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + this->forwarder->destroy(this->forwarder); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_forecast_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)register_forecast, NULL), + PLUGIN_PROVIDE(CUSTOM, "forecast"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_forecast_plugin_t *this) +{ + this->listener->destroy(this->listener); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *forecast_plugin_create() +{ + private_forecast_plugin_t *this; + + if (!lib->caps->keep(lib->caps, CAP_NET_RAW)) + { + DBG1(DBG_NET, "forecast plugin requires CAP_NET_RAW capability"); + return NULL; + } + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .listener = forecast_listener_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/forecast/forecast_plugin.h b/src/libcharon/plugins/forecast/forecast_plugin.h new file mode 100644 index 000000000..739ca4d79 --- /dev/null +++ b/src/libcharon/plugins/forecast/forecast_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010-2014 Martin Willi + * Copyright (C) 2010-2014 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 forecast forecast + * @ingroup cplugins + * + * @defgroup forecast_plugin forecast_plugin + * @{ @ingroup forecast + */ + +#ifndef FORECAST_PLUGIN_H_ +#define FORECAST_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct forecast_plugin_t forecast_plugin_t; + +/** + * Broadcast/Multicast forwarding plugin. + */ +struct forecast_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** FORECAST_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in index aa5bdb747..de74f88cc 100644 --- a/src/libcharon/plugins/ha/Makefile.in +++ b/src/libcharon/plugins/ha/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c index dd55fae8b..2b271a8e7 100644 --- a/src/libcharon/plugins/ha/ha_attribute.c +++ b/src/libcharon/plugins/ha/ha_attribute.c @@ -170,7 +170,7 @@ static bool responsible_for(private_ha_attribute_t *this, int bit) } METHOD(attribute_provider_t, acquire_address, host_t*, - private_ha_attribute_t *this, linked_list_t *pools, identification_t *id, + private_ha_attribute_t *this, linked_list_t *pools, ike_sa_t *ike_sa, host_t *requested) { enumerator_t *enumerator; @@ -233,7 +233,7 @@ METHOD(attribute_provider_t, acquire_address, host_t*, METHOD(attribute_provider_t, release_address, bool, private_ha_attribute_t *this, linked_list_t *pools, host_t *address, - identification_t *id) + ike_sa_t *ike_sa) { enumerator_t *enumerator; pool_t *pool; diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c index 60e75fc7e..6c1b3471d 100644 --- a/src/libcharon/plugins/ha/ha_cache.c +++ b/src/libcharon/plugins/ha/ha_cache.c @@ -196,9 +196,26 @@ static status_t rekey_children(ike_sa_t *ike_sa) enumerator_t *enumerator; child_sa_t *child_sa; status_t status = SUCCESS; + linked_list_t *children; + struct { + protocol_id_t protocol; + u_int32_t spi; + } *info; + children = linked_list_create(); enumerator = ike_sa->create_child_sa_enumerator(ike_sa); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + while (enumerator->enumerate(enumerator, &child_sa)) + { + INIT(info, + .protocol = child_sa->get_protocol(child_sa), + .spi = child_sa->get_spi(child_sa, TRUE), + ); + children->insert_last(children, info); + } + enumerator->destroy(enumerator); + + enumerator = children->create_enumerator(children); + while (enumerator->enumerate(enumerator, &info)) { if (ike_sa->supports_extension(ike_sa, EXT_MS_WINDOWS) && ike_sa->has_condition(ike_sa, COND_NAT_THERE)) @@ -207,17 +224,13 @@ static status_t rekey_children(ike_sa_t *ike_sa) * with an "invalid situation" error. We just close the CHILD_SA, * Windows will reestablish it immediately if required. */ DBG1(DBG_CFG, "resyncing CHILD_SA using a delete"); - status = ike_sa->delete_child_sa(ike_sa, - child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE), + status = ike_sa->delete_child_sa(ike_sa, info->protocol, info->spi, FALSE); } else { DBG1(DBG_CFG, "resyncing CHILD_SA using a rekey"); - status = ike_sa->rekey_child_sa(ike_sa, - child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + status = ike_sa->rekey_child_sa(ike_sa, info->protocol, info->spi); } if (status == DESTROY_ME) { @@ -225,6 +238,8 @@ static status_t rekey_children(ike_sa_t *ike_sa) } } enumerator->destroy(enumerator); + children->destroy_function(children, free); + return status; } diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index c166d72ac..17f2d50d1 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -97,7 +97,7 @@ METHOD(listener_t, child_keys, bool, } m->add_attribute(m, HA_NONCE_I, nonce_i); m->add_attribute(m, HA_NONCE_R, nonce_r); - if (dh && dh->get_shared_secret(dh, &secret) == SUCCESS) + if (dh && dh->get_shared_secret(dh, &secret)) { m->add_attribute(m, HA_SECRET, secret); chunk_clear(&secret); @@ -128,7 +128,7 @@ METHOD(listener_t, child_keys, bool, 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, + child_sa->get_unique_id(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) ? "*" : ""); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index e20e872c1..31eeb934e 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -81,17 +81,18 @@ struct ha_diffie_hellman_t { chunk_t pub; }; -METHOD(diffie_hellman_t, dh_get_shared_secret, status_t, +METHOD(diffie_hellman_t, dh_get_shared_secret, bool, ha_diffie_hellman_t *this, chunk_t *secret) { *secret = chunk_clone(this->secret); - return SUCCESS; + return TRUE; } -METHOD(diffie_hellman_t, dh_get_my_public_value, void, +METHOD(diffie_hellman_t, dh_get_my_public_value, bool, ha_diffie_hellman_t *this, chunk_t *value) { *value = chunk_clone(this->pub); + return TRUE; } METHOD(diffie_hellman_t, dh_destroy, void, @@ -373,6 +374,9 @@ static void process_ike_update(private_ha_dispatcher_t *this, else { DBG1(DBG_IKE, "HA is missing nodes peer configuration"); + charon->ike_sa_manager->checkin_and_destroy( + charon->ike_sa_manager, ike_sa); + ike_sa = NULL; } break; case HA_EXTENSIONS: @@ -718,7 +722,8 @@ static void process_child_add(private_ha_dispatcher_t *this, child_sa = child_sa_create(ike_sa->get_my_host(ike_sa), ike_sa->get_other_host(ike_sa), config, 0, - ike_sa->has_condition(ike_sa, COND_NAT_ANY)); + ike_sa->has_condition(ike_sa, COND_NAT_ANY), + 0, 0); child_sa->set_mode(child_sa, mode); child_sa->set_protocol(child_sa, PROTO_ESP); child_sa->set_ipcomp(child_sa, ipcomp); @@ -835,7 +840,7 @@ static void process_child_add(private_ha_dispatcher_t *this, 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, + child_sa->get_unique_id(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); diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index 442a3a23d..6b4b53c9c 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -84,7 +84,7 @@ METHOD(listener_t, ike_keys, bool, { /* do not sync SA between nodes */ return TRUE; } - if (dh->get_shared_secret(dh, &secret) != SUCCESS) + if (!dh->get_shared_secret(dh, &secret)) { return TRUE; } @@ -127,9 +127,11 @@ METHOD(listener_t, ike_keys, bool, chunk_clear(&secret); if (ike_sa->get_version(ike_sa) == IKEV1) { - dh->get_my_public_value(dh, &secret); - m->add_attribute(m, HA_LOCAL_DH, secret); - chunk_free(&secret); + if (dh->get_my_public_value(dh, &secret)) + { + m->add_attribute(m, HA_LOCAL_DH, secret); + chunk_free(&secret); + } m->add_attribute(m, HA_REMOTE_DH, dh_other); if (shared) { diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c index 493cad5ec..a58377bab 100644 --- a/src/libcharon/plugins/ha/ha_plugin.c +++ b/src/libcharon/plugins/ha/ha_plugin.c @@ -25,7 +25,6 @@ #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; @@ -108,13 +107,13 @@ static bool plugin_cb(private_ha_plugin_t *this, 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); + charon->attributes->add_provider(charon->attributes, + &this->attr->provider); } else { - hydra->attributes->remove_provider(hydra->attributes, - &this->attr->provider); + charon->attributes->remove_provider(charon->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); @@ -224,4 +223,3 @@ plugin_t *ha_plugin_create() return &this->public.plugin; } - diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in index bd3fd63aa..f98e78ffc 100644 --- a/src/libcharon/plugins/ipseckey/Makefile.in +++ b/src/libcharon/plugins/ipseckey/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in index 7e1f79bd8..7a2583d06 100644 --- a/src/libcharon/plugins/kernel_iph/Makefile.in +++ b/src/libcharon/plugins/kernel_iph/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in index c961c0bd8..6b6c95688 100644 --- a/src/libcharon/plugins/kernel_libipsec/Makefile.in +++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c index bd07a67a2..6246dc505 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c @@ -222,10 +222,10 @@ static inline bool policy_entry_equals(policy_entry_t *a, /** * Expiration callback */ -static void expire(u_int32_t reqid, u_int8_t protocol, u_int32_t spi, bool hard) +static void expire(u_int8_t protocol, u_int32_t spi, host_t *dst, bool hard) { - hydra->kernel_interface->expire(hydra->kernel_interface, reqid, protocol, - spi, hard); + hydra->kernel_interface->expire(hydra->kernel_interface, protocol, + spi, dst, hard); } METHOD(kernel_ipsec_t, get_features, kernel_feature_t, @@ -236,14 +236,14 @@ METHOD(kernel_ipsec_t, get_features, kernel_feature_t, METHOD(kernel_ipsec_t, get_spi, status_t, private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst, - u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) + u_int8_t protocol, u_int32_t *spi) { - return ipsec->sas->get_spi(ipsec->sas, src, dst, protocol, reqid, spi); + return ipsec->sas->get_spi(ipsec->sas, src, dst, protocol, spi); } METHOD(kernel_ipsec_t, get_cpi, status_t, private_kernel_libipsec_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t reqid, u_int16_t *cpi) + u_int16_t *cpi) { return NOT_SUPPORTED; } @@ -254,13 +254,13 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, - bool initiator, bool encap, bool esn, bool inbound, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts) + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts) { return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, - mode, ipcomp, cpi, initiator, encap, esn, inbound, - src_ts, dst_ts); + mode, ipcomp, cpi, initiator, encap, esn, + inbound, update); } METHOD(kernel_ipsec_t, update_sa, status_t, diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c index 6ce1d4eb0..830954e11 100644 --- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c +++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_router.c @@ -131,35 +131,6 @@ static void deliver_plain(private_kernel_libipsec_router_t *this, } /** - * Create an FD set covering all TUN devices and the read end of the notify pipe - */ -static int collect_fds(private_kernel_libipsec_router_t *this, fd_set *fds) -{ - enumerator_t *enumerator; - tun_entry_t *entry; - int maxfd; - - FD_ZERO(fds); - FD_SET(this->notify[0], fds); - maxfd = this->notify[0]; - - FD_SET(this->tun.fd, fds); - maxfd = max(maxfd, this->tun.fd); - - this->lock->read_lock(this->lock); - enumerator = this->tuns->create_enumerator(this->tuns); - while (enumerator->enumerate(enumerator, NULL, &entry)) - { - FD_SET(entry->fd, fds); - maxfd = max(maxfd, entry->fd); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - - return maxfd + 1; -} - -/** * Read and process outbound plaintext packet for the given TUN device */ static void process_plain(tun_device_t *tun) @@ -183,29 +154,20 @@ static void process_plain(tun_device_t *tun) } /** - * Handle waiting data for any TUN device + * Find flagged revents in a pollfd set by fd */ -static void handle_tuns(private_kernel_libipsec_router_t *this, fd_set *fds) +static int find_revents(struct pollfd *pfd, int count, int fd) { - enumerator_t *enumerator; - tun_entry_t *entry; + int i; - if (FD_ISSET(this->tun.fd, fds)) + for (i = 0; i < count; i++) { - process_plain(this->tun.tun); - } - - this->lock->read_lock(this->lock); - enumerator = this->tuns->create_enumerator(this->tuns); - while (enumerator->enumerate(enumerator, NULL, &entry)) - { - if (FD_ISSET(entry->fd, fds)) + if (pfd[i].fd == fd) { - process_plain(entry->tun); + return pfd[i].revents; } } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); + return 0; } /** @@ -213,28 +175,68 @@ static void handle_tuns(private_kernel_libipsec_router_t *this, fd_set *fds) */ static job_requeue_t handle_plain(private_kernel_libipsec_router_t *this) { + enumerator_t *enumerator; + tun_entry_t *entry; bool oldstate; - fd_set fds; - int maxfd; + int count = 0; + char buf[1]; + struct pollfd *pfd; + + this->lock->read_lock(this->lock); - maxfd = collect_fds(this, &fds); + pfd = alloca(sizeof(*pfd) * (this->tuns->get_count(this->tuns) + 2)); + pfd[count].fd = this->notify[0]; + pfd[count].events = POLLIN; + count++; + pfd[count].fd = this->tun.fd; + pfd[count].events = POLLIN; + count++; + + enumerator = this->tuns->create_enumerator(this->tuns); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + pfd[count].fd = entry->fd; + pfd[count].events = POLLIN; + count++; + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); oldstate = thread_cancelability(TRUE); - if (select(maxfd, &fds, NULL, NULL, NULL) <= 0) + if (poll(pfd, count, -1) <= 0) { thread_cancelability(oldstate); return JOB_REQUEUE_FAIR; } thread_cancelability(oldstate); - if (FD_ISSET(this->notify[0], &fds)) - { /* list of TUN devices changed, read notification data, rebuild FDs */ - char buf[1]; - while (read(this->notify[0], &buf, sizeof(buf)) == sizeof(buf)); + if (pfd[0].revents & POLLIN) + { + /* list of TUN devices changed, read notification data, rebuild FDs */ + while (read(this->notify[0], &buf, sizeof(buf)) == sizeof(buf)) + { + /* nop */ + } return JOB_REQUEUE_DIRECT; } - handle_tuns(this, &fds); + if (pfd[1].revents & POLLIN) + { + process_plain(this->tun.tun); + } + + this->lock->read_lock(this->lock); + enumerator = this->tuns->create_enumerator(this->tuns); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + if (find_revents(pfd, count, entry->fd) & POLLIN) + { + process_plain(entry->tun); + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + return JOB_REQUEUE_DIRECT; } diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in index 1c92e30fc..efb214b88 100644 --- a/src/libcharon/plugins/kernel_wfp/Makefile.in +++ b/src/libcharon/plugins/kernel_wfp/Makefile.in @@ -237,6 +237,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -297,10 +298,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -374,6 +377,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c index 41f85ba5c..2e31aa151 100644 --- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c +++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c @@ -54,6 +54,24 @@ const GUID FWPM_LAYER_IPFORWARD_V4 = { const GUID FWPM_LAYER_IPFORWARD_V6 = { 0x7b964818, 0x19c7, 0x493a, { 0xb7,0x1f,0x83,0x2c,0x36,0x84,0xd2,0x8c } }; +const GUID FWPM_LAYER_ALE_AUTH_CONNECT_V4 = { + 0xc38d57d1, 0x05a7, 0x4c33, { 0x90,0x4f,0x7f,0xbc,0xee,0xe6,0x0e,0x82 } +}; +const GUID FWPM_LAYER_ALE_AUTH_CONNECT_V6 = { + 0x4a72393b, 0x319f, 0x44bc, { 0x84,0xc3,0xba,0x54,0xdc,0xb3,0xb6,0xb4 } +}; +const GUID FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 = { + 0xe1cd9fe7, 0xf4b5, 0x4273, { 0x96,0xc0,0x59,0x2e,0x48,0x7b,0x86,0x50 } +}; +const GUID FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 = { + 0xa3b42c97, 0x9f04, 0x4672, { 0xb8,0x7e,0xce,0xe9,0xc4,0x83,0x25,0x7f } +}; +const GUID FWPM_SUBLAYER_IPSEC_TUNNEL = { + 0x83f299ed, 0x9ff4, 0x4967, { 0xaf,0xf4,0xc3,0x09,0xf4,0xda,0xb8,0x27 } +}; +const GUID FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL = { + 0xa5082e73, 0x8f71, 0x4559, { 0x8a,0x9a,0x10,0x1c,0xea,0x04,0xef,0x87 } +}; const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 = { 0x5132900d, 0x5e84, 0x4b5f, { 0x80,0xe4,0x01,0x74,0x1e,0x81,0xff,0x10 } }; @@ -90,6 +108,24 @@ const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 = { const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 = { 0xdae640cc, 0xe021, 0x4bee, { 0x9e,0xb6,0xa4,0x8b,0x27,0x5c,0x8c,0x1d } }; +const GUID FWPM_CALLOUT_IPSEC_ALE_CONNECT_V4 = { + 0x6ac141fc, 0xf75d, 0x4203, { 0xb9,0xc8,0x48,0xe6,0x14,0x9c,0x27,0x12 } +}; +const GUID FWPM_CALLOUT_IPSEC_ALE_CONNECT_V6 = { + 0x4c0dda05, 0xe31f, 0x4666, { 0x90,0xb0,0xb3,0xdf,0xad,0x34,0x12,0x9a } +}; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V4 = { + 0x3df6e7de, 0xfd20, 0x48f2, { 0x9f,0x26,0xf8,0x54,0x44,0x4c,0xba,0x79 } +}; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V6 = { + 0xa1e392d3, 0x72ac, 0x47bb, { 0x87,0xa7,0x01,0x22,0xc6,0x94,0x34,0xab } +}; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_INITIATE_SECURE_V4 = { + 0x7dff309b, 0xba7d, 0x4aba, { 0x91,0xaa,0xae,0x5c,0x66,0x40,0xc9,0x44 } +}; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_INITIATE_SECURE_V6 = { + 0xa9a0d6d9, 0xc58c, 0x474e, { 0x8a,0xeb,0x3c,0xfe,0x99,0xd6,0xd5,0x3d } +}; /** * Load a function symbol from a loaded dll diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h index 50a89a007..a553a0986 100644 --- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h +++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h @@ -127,6 +127,10 @@ const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4; const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6; const GUID FWPM_LAYER_IPFORWARD_V4; const GUID FWPM_LAYER_IPFORWARD_V6; +const GUID FWPM_LAYER_ALE_AUTH_CONNECT_V4; +const GUID FWPM_LAYER_ALE_AUTH_CONNECT_V6; +const GUID FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4; +const GUID FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6; const GUID FWPM_SUBLAYER_IPSEC_TUNNEL; const GUID FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL; const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4; @@ -141,6 +145,12 @@ const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4; const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6; const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4; const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6; +const GUID FWPM_CALLOUT_IPSEC_ALE_CONNECT_V4; +const GUID FWPM_CALLOUT_IPSEC_ALE_CONNECT_V6; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V4; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V6; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_INITIATE_SECURE_V4; +const GUID FWPM_CALLOUT_IPSEC_INBOUND_INITIATE_SECURE_V6; /* integrity config, missing in some MinGW versions */ #ifndef IPSEC_AUTH_CONFIG_HMAC_MD5_96 diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c index c788bfb10..b38ded846 100644 --- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c +++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c @@ -26,6 +26,8 @@ #include <collections/hashtable.h> #include <processing/jobs/callback_job.h> +#define IPPROTO_IPIP 4 +#define IPPROTO_IPV6 41 typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t; @@ -188,6 +190,14 @@ typedef struct { u_int64_t provider; /** WFP allocated LUID for SA context */ u_int64_t sa_id; + /** WFP allocated LUID for tunnel mode IP-IPv4 inbound filter */ + u_int64_t ip_ipv4_in; + /** WFP allocated LUID for tunnel mode IP-IPv4 outbound filter */ + u_int64_t ip_ipv4_out; + /** WFP allocated LUID for tunnel mode IP-IPv6 inbound filter */ + u_int64_t ip_ipv6_in; + /** WFP allocated LUID for tunnel mode IP-IPv6 outbound filter */ + u_int64_t ip_ipv6_out; } entry_t; /** @@ -285,6 +295,22 @@ static void cleanup_policies(private_kernel_wfp_ipsec_t *this, entry_t *entry) */ static void entry_destroy(private_kernel_wfp_ipsec_t *this, entry_t *entry) { + if (entry->ip_ipv4_in) + { + FwpmFilterDeleteById0(this->handle, entry->ip_ipv4_in); + } + if (entry->ip_ipv4_out) + { + FwpmFilterDeleteById0(this->handle, entry->ip_ipv4_out); + } + if (entry->ip_ipv6_in) + { + FwpmFilterDeleteById0(this->handle, entry->ip_ipv6_in); + } + if (entry->ip_ipv6_out) + { + FwpmFilterDeleteById0(this->handle, entry->ip_ipv6_out); + } if (entry->sa_id) { IPsecSaContextDeleteById0(this->handle, entry->sa_id); @@ -553,49 +579,58 @@ static void free_conditions(FWPM_FILTER_CONDITION0 *conds, int count) * Find the callout GUID for given parameters */ static bool find_callout(bool tunnel, bool v6, bool inbound, bool forward, - GUID *layer, GUID *sublayer, GUID *callout) + bool ale, GUID *layer, GUID *sublayer, GUID *callout) { struct { bool tunnel; bool v6; bool inbound; bool forward; + bool ale; const GUID *layer; const GUID *sublayer; const GUID *callout; } map[] = { - { 0, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, NULL, - &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4 }, - { 0, 0, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4, NULL, - &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 }, - { 0, 1, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, NULL, - &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6 }, - { 0, 1, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6, NULL, - &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6 }, - { 1, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 }, - { 1, 0, 0, 1, &FWPM_LAYER_IPFORWARD_V4, - &FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL, - &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 }, - { 1, 0, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 }, - { 1, 0, 1, 1, &FWPM_LAYER_IPFORWARD_V4, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 }, - { 1, 1, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 }, - { 1, 1, 0, 1, &FWPM_LAYER_IPFORWARD_V6, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 }, - { 1, 1, 1, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 }, - { 1, 1, 1, 1, &FWPM_LAYER_IPFORWARD_V6, - &FWPM_SUBLAYER_IPSEC_TUNNEL, - &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 }, + { 0, 0, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, NULL, + &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4 }, + { 0, 0, 1, 0, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4, NULL, + &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 }, + { 0, 1, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, NULL, + &FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6 }, + { 0, 1, 1, 0, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6, NULL, + &FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6 }, + { 1, 0, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 }, + { 1, 0, 0, 1, 0, &FWPM_LAYER_IPFORWARD_V4, + &FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL, + &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 }, + { 1, 0, 1, 0, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V4, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 }, + { 1, 0, 1, 1, 0, &FWPM_LAYER_IPFORWARD_V4, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 }, + { 1, 0, 0, 0, 1, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, NULL, + &FWPM_CALLOUT_IPSEC_ALE_CONNECT_V4 }, + { 1, 0, 1, 0, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, NULL, + &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V4}, + { 1, 1, 0, 0, 0, &FWPM_LAYER_OUTBOUND_TRANSPORT_V6, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 }, + { 1, 1, 0, 1, 0, &FWPM_LAYER_IPFORWARD_V6, + &FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL, + &FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 }, + { 1, 1, 1, 0, 0, &FWPM_LAYER_INBOUND_TRANSPORT_V6, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 }, + { 1, 1, 1, 1, 0, &FWPM_LAYER_IPFORWARD_V6, + &FWPM_SUBLAYER_IPSEC_TUNNEL, + &FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 }, + { 1, 1, 0, 0, 1, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, NULL, + &FWPM_CALLOUT_IPSEC_ALE_CONNECT_V6 }, + { 1, 1, 1, 0, 1, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, NULL, + &FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_ALE_ACCEPT_V6}, }; int i; @@ -604,7 +639,8 @@ static bool find_callout(bool tunnel, bool v6, bool inbound, bool forward, if (tunnel == map[i].tunnel && v6 == map[i].v6 && inbound == map[i].inbound && - forward == map[i].forward) + forward == map[i].forward && + ale == map[i].ale) { *callout = *map[i].callout; *layer = *map[i].layer; @@ -647,7 +683,7 @@ static bool install_sp(private_kernel_wfp_ipsec_t *this, sp_entry_t *sp, } v6 = sp->src->get_type(sp->src) == TS_IPV6_ADDR_RANGE; - if (!find_callout(context != NULL, v6, inbound, fwd, + if (!find_callout(context != NULL, v6, inbound, fwd, FALSE, &filter.layerKey, &filter.subLayerKey, &filter.action.calloutKey)) { @@ -688,8 +724,73 @@ static bool install_sp(private_kernel_wfp_ipsec_t *this, sp_entry_t *sp, free_conditions(conds, count); if (res != ERROR_SUCCESS) { - DBG1(DBG_KNL, "installing %s%sbound WFP filter failed: 0x%08x", - fwd ? "forward " : "", inbound ? "in" : "out", res); + DBG1(DBG_KNL, "installing IPv%d %s%sbound %s WFP filter failed: 0x%08x", + v6 ? 6 : 4, fwd ? "forward " : "", inbound ? "in" : "out", + context ? "tunnel" : "transport", res); + return FALSE; + } + return TRUE; +} + +/** + * Install an IP-IP allow filter for SA specific hosts + */ +static bool install_ipip_ale(private_kernel_wfp_ipsec_t *this, + host_t *local, host_t *remote, GUID *context, + bool inbound, int proto, u_int64_t *filter_id) +{ + traffic_selector_t *lts, *rts; + FWPM_FILTER_CONDITION0 *conds = NULL; + int count = 0; + bool v6; + DWORD res; + FWPM_FILTER0 filter = { + .displayData = { + .name = L"charon IPsec IP-in-IP ALE policy", + }, + .action = { + .type = FWP_ACTION_CALLOUT_TERMINATING, + }, + }; + + if (context) + { + filter.flags |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT; + filter.providerKey = (GUID*)&this->provider.providerKey; + filter.providerContextKey = *context; + } + + v6 = local->get_family(local) == AF_INET6; + if (!find_callout(TRUE, v6, inbound, FALSE, TRUE, &filter.layerKey, + &filter.subLayerKey, &filter.action.calloutKey)) + { + return FALSE; + } + + lts = traffic_selector_create_from_subnet(local->clone(local), + v6 ? 128 : 32 , proto, 0, 65535); + rts = traffic_selector_create_from_subnet(remote->clone(remote), + v6 ? 128 : 32 , proto, 0, 65535); + if (!ts2condition(lts, &FWPM_CONDITION_IP_LOCAL_ADDRESS, &conds, &count) || + !ts2condition(rts, &FWPM_CONDITION_IP_REMOTE_ADDRESS, &conds, &count)) + { + free_conditions(conds, count); + lts->destroy(lts); + rts->destroy(rts); + return FALSE; + } + lts->destroy(lts); + rts->destroy(rts); + + filter.numFilterConditions = count; + filter.filterCondition = conds; + + res = FwpmFilterAdd0(this->handle, &filter, NULL, filter_id); + free_conditions(conds, count); + if (res != ERROR_SUCCESS) + { + DBG1(DBG_KNL, "installing IP-IPv%d %s ALE WFP filter failed: 0x%08x", + v6 ? 6 : 4, inbound ? "inbound" : "outbound", res); return FALSE; } return TRUE; @@ -703,10 +804,21 @@ static bool install_sps(private_kernel_wfp_ipsec_t *this, { enumerator_t *enumerator; sp_entry_t *sp; + bool has_v4 = FALSE, has_v6 = FALSE; enumerator = array_create_enumerator(entry->sps); while (enumerator->enumerate(enumerator, &sp)) { + switch (sp->src->get_type(sp->src)) + { + case TS_IPV4_ADDR_RANGE: + has_v4 = TRUE; + break; + case TS_IPV6_ADDR_RANGE: + has_v6 = TRUE; + break; + } + /* inbound policy */ if (!install_sp(this, sp, context, TRUE, FALSE, &sp->policy_in)) { @@ -719,21 +831,22 @@ static bool install_sps(private_kernel_wfp_ipsec_t *this, enumerator->destroy(enumerator); return FALSE; } + if (context) { if (!sp->src->is_host(sp->src, entry->local) || !sp->dst->is_host(sp->dst, entry->remote)) { /* inbound forward policy, from decapsulation */ - if (!install_sp(this, sp, context, - TRUE, TRUE, &sp->policy_fwd_in)) + if (!install_sp(this, sp, context, TRUE, TRUE, + &sp->policy_fwd_in)) { enumerator->destroy(enumerator); return FALSE; } /* outbound forward policy, to encapsulate */ - if (!install_sp(this, sp, context, - FALSE, TRUE, &sp->policy_fwd_out)) + if (!install_sp(this, sp, context, FALSE, TRUE, + &sp->policy_fwd_out)) { enumerator->destroy(enumerator); return FALSE; @@ -743,6 +856,38 @@ static bool install_sps(private_kernel_wfp_ipsec_t *this, } enumerator->destroy(enumerator); + if (context) + { + /* In tunnel mode, Windows does firewall filtering on decrypted but + * non-unwrapped packets: It sees them as IP-in-IP packets. When using + * a default-drop policy, we need to allow such packets explicitly. */ + if (has_v4) + { + if (!install_ipip_ale(this, entry->local, entry->remote, context, + TRUE, IPPROTO_IPIP, &entry->ip_ipv4_in)) + { + return FALSE; + } + if (!install_ipip_ale(this, entry->local, entry->remote, NULL, + FALSE, IPPROTO_IPIP, &entry->ip_ipv4_out)) + { + return FALSE; + } + } + if (has_v6) + { + if (!install_ipip_ale(this, entry->local, entry->remote, context, + TRUE, IPPROTO_IPV6, &entry->ip_ipv6_in)) + { + return FALSE; + } + if (!install_ipip_ale(this, entry->local, entry->remote, NULL, + FALSE, IPPROTO_IPV6, &entry->ip_ipv6_out)) + { + return FALSE; + } + } + } return TRUE; } @@ -1583,8 +1728,20 @@ static void WINAPI event_callback(void *user, const FWPM_NET_EVENT1 *event) acquire(this, event->classifyDrop->filterId, local, remote); break; case FWPM_NET_EVENT_TYPE_IKEEXT_MM_FAILURE: + DBG1(DBG_KNL, "WFP MM failure: %R === %R, 0x%08x, filterId %llu", + local, remote, event->ikeMmFailure->failureErrorCode, + event->ikeMmFailure->mmFilterId); + break; case FWPM_NET_EVENT_TYPE_IKEEXT_QM_FAILURE: + DBG1(DBG_KNL, "WFP QM failure: %R === %R, 0x%08x, filterId %llu", + local, remote, event->ikeQmFailure->failureErrorCode, + event->ikeQmFailure->qmFilterId); + break; case FWPM_NET_EVENT_TYPE_IKEEXT_EM_FAILURE: + DBG1(DBG_KNL, "WFP EM failure: %R === %R, 0x%08x, filterId %llu", + local, remote, event->ikeEmFailure->failureErrorCode, + event->ikeEmFailure->qmFilterId); + break; case FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP: DBG1(DBG_KNL, "IPsec kernel drop: %R === %R, error 0x%08x, " "SPI 0x%08x, %s filterId %llu", local, remote, @@ -1824,7 +1981,7 @@ static u_int permute(u_int x, u_int p) METHOD(kernel_ipsec_t, get_spi, status_t, private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst, - u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) + u_int8_t protocol, u_int32_t *spi) { /* To avoid sequencial SPIs, we use a one-to-one permuation function on * an incrementing counter, that is a full period PRNG for the range we @@ -1841,7 +1998,7 @@ METHOD(kernel_ipsec_t, get_spi, status_t, METHOD(kernel_ipsec_t, get_cpi, status_t, private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t reqid, u_int16_t *cpi) + u_int16_t *cpi) { return NOT_SUPPORTED; } @@ -1875,9 +2032,8 @@ static void expire_data_destroy(expire_data_t *data) static job_requeue_t expire_job(expire_data_t *data) { private_kernel_wfp_ipsec_t *this = data->this; - u_int32_t reqid = 0; u_int8_t protocol; - entry_t *entry; + entry_t *entry = NULL; sa_entry_t key = { .spi = data->spi, .dst = data->dst, @@ -1891,7 +2047,6 @@ static job_requeue_t expire_job(expire_data_t *data) if (entry) { protocol = entry->isa.protocol; - reqid = entry->reqid; if (entry->osa.dst) { key.dst = entry->osa.dst; @@ -1908,15 +2063,14 @@ static job_requeue_t expire_job(expire_data_t *data) if (entry) { protocol = entry->isa.protocol; - reqid = entry->reqid; } this->mutex->unlock(this->mutex); } - if (reqid) + if (entry) { - hydra->kernel_interface->expire(hydra->kernel_interface, - reqid, protocol, data->spi, data->hard); + hydra->kernel_interface->expire(hydra->kernel_interface, protocol, + data->spi, data->dst, data->hard); } return JOB_REQUEUE_NONE; @@ -1949,8 +2103,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, - bool initiator, bool encap, bool esn, bool inbound, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts) + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts) { host_t *local, *remote; entry_t *entry; diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in index db4552dde..7942868f6 100644 --- a/src/libcharon/plugins/led/Makefile.in +++ b/src/libcharon/plugins/led/Makefile.in @@ -226,6 +226,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -286,10 +287,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -363,6 +366,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in index 418dccba5..52dbec53f 100644 --- a/src/libcharon/plugins/load_tester/Makefile.in +++ b/src/libcharon/plugins/load_tester/Makefile.in @@ -239,6 +239,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -299,10 +300,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -376,6 +379,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index bc7c0ffbc..8a500635c 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -394,6 +394,28 @@ static void generate_auth_cfg(private_load_tester_config_t *this, char *str, } } } + else if (strpfx(str, "xauth")) + { /* XAuth, use a username */ + class = AUTH_CLASS_XAUTH; + if (*(str + strlen("xauth")) == '-') + { + auth->add(auth, AUTH_RULE_XAUTH_BACKEND, str + strlen("xauth-")); + } + if (!id) + { + if (local && num) + { + snprintf(buf, sizeof(buf), "cli-%.6d-%.2d", num, rnd); + id = identification_create_from_string(buf); + } + else + { + id = identification_create_from_encoding(ID_ANY, chunk_empty); + } + } + /* additionally set the ID as XAuth identity */ + auth->add(auth, AUTH_RULE_XAUTH_IDENTITY, id->clone(id)); + } else { if (!streq(str, "pubkey")) @@ -618,7 +640,7 @@ static host_t *allocate_addr(private_load_tester_config_t *this, uint num) enumerator = this->pools->create_enumerator(this->pools); while (enumerator->enumerate(enumerator, &pool)) { - found = pool->acquire_address(pool, id, requested, MEM_POOL_NEW); + found = pool->acquire_address(pool, id, requested, MEM_POOL_NEW, NULL); if (found) { iface = (char*)pool->get_name(pool); diff --git a/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c index d5ec3599b..e1c7c0e0b 100644 --- a/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c +++ b/src/libcharon/plugins/load_tester/load_tester_diffie_hellman.c @@ -15,33 +15,38 @@ #include "load_tester_diffie_hellman.h" -/** - * Implementation of gmp_diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(load_tester_diffie_hellman_t *this, - chunk_t *value) +METHOD(diffie_hellman_t, get_my_public_value, bool, + load_tester_diffie_hellman_t *this, chunk_t *value) { *value = chunk_empty; + return TRUE; } -/** - * Implementation of gmp_diffie_hellman_t.get_shared_secret. - */ -static status_t get_shared_secret(load_tester_diffie_hellman_t *this, - chunk_t *secret) +METHOD(diffie_hellman_t, set_other_public_value, bool, + load_tester_diffie_hellman_t *this, chunk_t value) +{ + return TRUE; +} + +METHOD(diffie_hellman_t, get_shared_secret, bool, + load_tester_diffie_hellman_t *this, chunk_t *secret) { *secret = chunk_empty; - return SUCCESS; + return TRUE; } -/** - * Implementation of gmp_diffie_hellman_t.get_dh_group. - */ -static diffie_hellman_group_t get_dh_group(load_tester_diffie_hellman_t *this) +METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, + load_tester_diffie_hellman_t *this) { return MODP_NULL; } +METHOD(diffie_hellman_t, destroy, void, + load_tester_diffie_hellman_t *this) +{ + free(this); +} + /** * See header */ @@ -55,13 +60,15 @@ load_tester_diffie_hellman_t *load_tester_diffie_hellman_create( return NULL; } - this = malloc_thing(load_tester_diffie_hellman_t); - - this->dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *))get_shared_secret; - this->dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t ))nop; - this->dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *))get_my_public_value; - this->dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *))get_dh_group; - this->dh.destroy = (void (*)(diffie_hellman_t *))free; + INIT(this, + .dh = { + .get_shared_secret = _get_shared_secret, + .set_other_public_value = _set_other_public_value, + .get_my_public_value = _get_my_public_value, + .get_dh_group = _get_dh_group, + .destroy = _destroy, + } + ); return this; } diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c index 3f256ddd0..62d43e302 100644 --- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c +++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c @@ -36,7 +36,7 @@ struct private_load_tester_ipsec_t { METHOD(kernel_ipsec_t, get_spi, status_t, private_load_tester_ipsec_t *this, host_t *src, host_t *dst, - u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) + u_int8_t protocol, u_int32_t *spi) { *spi = (uint32_t)ref_get(&this->spi); return SUCCESS; @@ -44,7 +44,7 @@ METHOD(kernel_ipsec_t, get_spi, status_t, 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) + u_int16_t *cpi) { return FAILED; } @@ -55,8 +55,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, - bool initiator, bool encap, bool esn, bool inbound, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts) + bool initiator, bool encap, bool esn, bool inbound, bool update, + linked_list_t *src_ts, linked_list_t *dst_ts) { return SUCCESS; } diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in index f0f2c75f4..264c58ff5 100644 --- a/src/libcharon/plugins/lookip/Makefile.in +++ b/src/libcharon/plugins/lookip/Makefile.in @@ -235,6 +235,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -295,10 +296,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -372,6 +375,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in index 3a866e968..76c9012b2 100644 --- a/src/libcharon/plugins/maemo/Makefile.in +++ b/src/libcharon/plugins/maemo/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in index e0f70ce44..35740c369 100644 --- a/src/libcharon/plugins/medcli/Makefile.in +++ b/src/libcharon/plugins/medcli/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in index adb61e817..8fe160ef3 100644 --- a/src/libcharon/plugins/medsrv/Makefile.in +++ b/src/libcharon/plugins/medsrv/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in index a0c21c442..9a5e438e1 100644 --- a/src/libcharon/plugins/osx_attr/Makefile.in +++ b/src/libcharon/plugins/osx_attr/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.c b/src/libcharon/plugins/osx_attr/osx_attr_handler.c index 9a3b2701d..d974b57ce 100644 --- a/src/libcharon/plugins/osx_attr/osx_attr_handler.c +++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.c @@ -169,7 +169,7 @@ static bool manage_dns(int family, chunk_t data, bool add) } METHOD(attribute_handler_t, handle, bool, - private_osx_attr_handler_t *this, identification_t *id, + private_osx_attr_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -182,7 +182,7 @@ METHOD(attribute_handler_t, handle, bool, } METHOD(attribute_handler_t, release, void, - private_osx_attr_handler_t *this, identification_t *server, + private_osx_attr_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -206,7 +206,7 @@ METHOD(enumerator_t, enumerate_dns, bool, } METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, - private_osx_attr_handler_t *this, identification_t *id, + private_osx_attr_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips) { enumerator_t *enumerator; diff --git a/src/libcharon/plugins/osx_attr/osx_attr_plugin.c b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c index 380483c23..4be9eda5e 100644 --- a/src/libcharon/plugins/osx_attr/osx_attr_plugin.c +++ b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c @@ -16,7 +16,6 @@ #include "osx_attr_plugin.h" #include "osx_attr_handler.h" -#include <hydra.h> #include <daemon.h> typedef struct private_osx_attr_plugin_t private_osx_attr_plugin_t; @@ -51,13 +50,13 @@ static bool plugin_cb(private_osx_attr_plugin_t *this, { if (reg) { - hydra->attributes->add_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); } else { - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); } return TRUE; } diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in index 14abba99a..baff3fc76 100644 --- a/src/libcharon/plugins/radattr/Makefile.in +++ b/src/libcharon/plugins/radattr/Makefile.in @@ -230,6 +230,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -290,10 +291,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -367,6 +370,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am new file mode 100644 index 000000000..9cfc370c0 --- /dev/null +++ b/src/libcharon/plugins/resolve/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -DRESOLV_CONF=\"${resolv_conf}\" + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +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/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in new file mode 100644 index 000000000..91479bf52 --- /dev/null +++ b/src/libcharon/plugins/resolve/Makefile.in @@ -0,0 +1,781 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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/resolve +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +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__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +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) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libstrongswan_resolve_la_LINK = $(LIBTOOL) $(AM_V_lt) --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 \ +@MONOLITHIC_FALSE@ $(plugindir) +@MONOLITHIC_TRUE@am_libstrongswan_resolve_la_rpath = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libstrongswan_resolve_la_SOURCES) +DIST_SOURCES = $(libstrongswan_resolve_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon \ + -DRESOLV_CONF=\"${resolv_conf}\" + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +@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 + +libstrongswan_resolve_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/resolve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) + @$(NORMAL_INSTALL) + @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 " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ + 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)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libstrongswan-resolve.la: $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_DEPENDENCIES) $(EXTRA_libstrongswan_resolve_la_DEPENDENCIES) + $(AM_V_CCLD)$(libstrongswan_resolve_la_LINK) $(am_libstrongswan_resolve_la_rpath) $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +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@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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 TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \ + cscopelist-am ctags ctags-am 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 tags-am 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/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c new file mode 100644 index 000000000..74c3960ff --- /dev/null +++ b/src/libcharon/plugins/resolve/resolve_handler.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * 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 <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <hydra.h> +#include <utils/debug.h> +#include <threading/mutex.h> + +/* path to resolvconf executable */ +#define RESOLVCONF_EXEC "/sbin/resolvconf" + +/* default prefix used for resolvconf interfaces (should have high prio) */ +#define RESOLVCONF_PREFIX "lo.inet.ipsec." + +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; + + /** + * use resolvconf instead of writing directly to resolv.conf + */ + bool use_resolvconf; + + /** + * prefix to be used for interface names sent to resolvconf + */ + char *iface_prefix; + + /** + * Mutex to access file exclusively + */ + mutex_t *mutex; +}; + +/** + * Writes the given nameserver to resolv.conf + */ +static bool write_nameserver(private_resolve_handler_t *this, + identification_t *server, host_t *addr) +{ + FILE *in, *out; + char buf[1024]; + size_t len; + bool handled = FALSE; + + 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); + } + return handled; +} + +/** + * Removes the given nameserver from resolv.conf + */ +static void remove_nameserver(private_resolve_handler_t *this, + identification_t *server, host_t *addr) +{ + FILE *in, *out; + char line[1024], matcher[512]; + + 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) + { + snprintf(matcher, sizeof(matcher), + "nameserver %H # by strongSwan, from %Y\n", + addr, server); + + /* copy all, but matching line */ + while (fgets(line, sizeof(line), in)) + { + if (strpfx(line, matcher)) + { + DBG1(DBG_IKE, "removing DNS server %H from %s", + addr, this->file); + } + else + { + fputs(line, out); + } + } + fclose(out); + } + fclose(in); + } +} + +/** + * Add or remove the given nameserver by invoking resolvconf. + */ +static bool invoke_resolvconf(private_resolve_handler_t *this, + identification_t *server, host_t *addr, + bool install) +{ + char cmd[128]; + bool success = TRUE; + + /* we use the nameserver's IP address as part of the interface name to + * make them unique */ + if (snprintf(cmd, sizeof(cmd), "%s %s %s%H", RESOLVCONF_EXEC, + install ? "-a" : "-d", this->iface_prefix, addr) >= sizeof(cmd)) + { + return FALSE; + } + + if (install) + { + FILE *out; + + out = popen(cmd, "w"); + if (!out) + { + return FALSE; + } + DBG1(DBG_IKE, "installing DNS server %H via resolvconf", addr); + fprintf(out, "nameserver %H\n", addr); + success = !ferror(out); + if (pclose(out)) + { + return FALSE; + } + } + else + { + ignore_result(system(cmd)); + } + return success; +} + +METHOD(attribute_handler_t, handle, bool, + private_resolve_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + identification_t *server; + host_t *addr; + bool handled; + + 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; + } + server = ike_sa->get_other_id(ike_sa); + + this->mutex->lock(this->mutex); + if (this->use_resolvconf) + { + handled = invoke_resolvconf(this, server, addr, TRUE); + } + else + { + handled = write_nameserver(this, server, addr); + } + this->mutex->unlock(this->mutex); + addr->destroy(addr); + + if (!handled) + { + DBG1(DBG_IKE, "adding DNS server failed"); + } + return handled; +} + +METHOD(attribute_handler_t, release, void, + private_resolve_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + identification_t *server; + 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; + } + addr = host_create_from_chunk(family, data, 0); + server = ike_sa->get_other_id(ike_sa); + + this->mutex->lock(this->mutex); + if (this->use_resolvconf) + { + invoke_resolvconf(this, server, addr, FALSE); + } + else + { + remove_nameserver(this, server, addr); + } + this->mutex->unlock(this->mutex); + + addr->destroy(addr); +} + +/** + * Attribute enumerator implementation + */ +typedef struct { + /** implements enumerator_t interface */ + enumerator_t public; + /** request IPv4 DNS? */ + bool v4; + /** request IPv6 DNS? */ + bool v6; +} attribute_enumerator_t; + +static bool attribute_enumerate(attribute_enumerator_t *this, + configuration_attribute_type_t *type, + chunk_t *data) +{ + if (this->v4) + { + *type = INTERNAL_IP4_DNS; + *data = chunk_empty; + this->v4 = FALSE; + return TRUE; + } + if (this->v6) + { + *type = INTERNAL_IP6_DNS; + *data = chunk_empty; + this->v6 = FALSE; + return TRUE; + } + return FALSE; +} + +/** + * Check if a list has a host of given family + */ +static bool has_host_family(linked_list_t *list, int family) +{ + enumerator_t *enumerator; + host_t *host; + bool found = FALSE; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &host)) + { + if (host->get_family(host) == family) + { + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + + return found; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, + private_resolve_handler_t *this, ike_sa_t *ike_sa, + linked_list_t *vips) +{ + attribute_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)attribute_enumerate, + .destroy = (void*)free, + }, + .v4 = has_host_family(vips, AF_INET), + .v6 = has_host_family(vips, AF_INET6), + ); + return &enumerator->public; +} + +METHOD(resolve_handler_t, destroy, void, + 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; + struct stat st; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = _release, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + .file = lib->settings->get_str(lib->settings, "%s.plugins.resolve.file", + RESOLV_CONF, lib->ns), + ); + + if (stat(RESOLVCONF_EXEC, &st) == 0) + { + this->use_resolvconf = TRUE; + this->iface_prefix = lib->settings->get_str(lib->settings, + "%s.plugins.resolve.resolvconf.iface_prefix", + RESOLVCONF_PREFIX, lib->ns); + } + + return &this->public; +} diff --git a/src/libcharon/plugins/resolve/resolve_handler.h b/src/libcharon/plugins/resolve/resolve_handler.h new file mode 100644 index 000000000..77bf9781c --- /dev/null +++ b/src/libcharon/plugins/resolve/resolve_handler.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup resolve_handler resolve_handler + * @{ @ingroup resolve + */ + +#ifndef RESOLVE_HANDLER_H_ +#define RESOLVE_HANDLER_H_ + +#include <attributes/attribute_handler.h> + +typedef struct resolve_handler_t resolve_handler_t; + +/** + * Handle DNS configuration attributes by mangling a resolv.conf file. + */ +struct resolve_handler_t { + + /** + * Implements the attribute_handler_t interface + */ + attribute_handler_t handler; + + /** + * Destroy a resolve_handler_t. + */ + void (*destroy)(resolve_handler_t *this); +}; + +/** + * Create a resolve_handler instance. + */ +resolve_handler_t *resolve_handler_create(); + +#endif /** RESOLVE_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/resolve/resolve_plugin.c b/src/libcharon/plugins/resolve/resolve_plugin.c new file mode 100644 index 000000000..193c5b602 --- /dev/null +++ b/src/libcharon/plugins/resolve/resolve_plugin.c @@ -0,0 +1,101 @@ +/* + * 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 <daemon.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 registered DNS attribute handler + */ + resolve_handler_t *handler; +}; + +METHOD(plugin_t, get_name, char*, + private_resolve_plugin_t *this) +{ + return "resolve"; +} + +/** + * Register handler + */ +static bool plugin_cb(private_resolve_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); + } + else + { + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_resolve_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "resolve"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_resolve_plugin_t *this) +{ + this->handler->destroy(this->handler); + free(this); +} + +/* + * see header file + */ +plugin_t *resolve_plugin_create() +{ + private_resolve_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .handler = resolve_handler_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/resolve/resolve_plugin.h b/src/libcharon/plugins/resolve/resolve_plugin.h new file mode 100644 index 000000000..0148b10d7 --- /dev/null +++ b/src/libcharon/plugins/resolve/resolve_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup resolve resolve + * @ingroup cplugins + * + * @defgroup resolve_plugin resolve_plugin + * @{ @ingroup resolve + */ + +#ifndef RESOLVE_PLUGIN_H_ +#define RESOLVE_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct resolve_plugin_t resolve_plugin_t; + +/** + * Plugin that writes received DNS servers in a resolv.conf file. + */ +struct resolve_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** RESOLVE_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in index 7c5b030f4..572e7fc2f 100644 --- a/src/libcharon/plugins/smp/Makefile.in +++ b/src/libcharon/plugins/smp/Makefile.in @@ -227,6 +227,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -287,10 +288,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -364,6 +367,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in index 548524a38..25b40995b 100644 --- a/src/libcharon/plugins/socket_default/Makefile.in +++ b/src/libcharon/plugins/socket_default/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 9cc39955b..dbfddbb81 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -141,6 +141,11 @@ struct private_socket_default_socket_t { * TRUE if the source address should be set on outbound packets */ bool set_source; + + /** + * A counter to implement round-robin selection of read sockets + */ + u_int rr_counter; }; METHOD(socket_t, receiver, status_t, @@ -150,66 +155,43 @@ METHOD(socket_t, receiver, status_t, chunk_t data; packet_t *pkt; host_t *source = NULL, *dest = NULL; - int bytes_read = 0; + int i, rr, index, bytes_read = 0, selected = -1; bool oldstate; - - fd_set rfds; - int max_fd = 0, selected = 0; u_int16_t port = 0; - - FD_ZERO(&rfds); - - if (this->ipv4 != -1) - { - FD_SET(this->ipv4, &rfds); - max_fd = max(max_fd, this->ipv4); - } - if (this->ipv4_natt != -1) - { - FD_SET(this->ipv4_natt, &rfds); - max_fd = max(max_fd, this->ipv4_natt); - } - if (this->ipv6 != -1) - { - FD_SET(this->ipv6, &rfds); - max_fd = max(max_fd, this->ipv6); - } - if (this->ipv6_natt != -1) - { - FD_SET(this->ipv6_natt, &rfds); - max_fd = max(max_fd, this->ipv6_natt); - } + struct pollfd pfd[] = { + { .fd = this->ipv4, .events = POLLIN }, + { .fd = this->ipv4_natt, .events = POLLIN }, + { .fd = this->ipv6, .events = POLLIN }, + { .fd = this->ipv6_natt, .events = POLLIN }, + }; + int ports[] = { + /* port numbers associated to pollfds */ + this->port, this->natt, this->port, this->natt, + }; DBG2(DBG_NET, "waiting for data on sockets"); oldstate = thread_cancelability(TRUE); - if (select(max_fd + 1, &rfds, NULL, NULL, NULL) <= 0) + if (poll(pfd, countof(pfd), -1) <= 0) { thread_cancelability(oldstate); return FAILED; } thread_cancelability(oldstate); - if (this->ipv4 != -1 && FD_ISSET(this->ipv4, &rfds)) + rr = this->rr_counter++; + for (i = 0; i < countof(pfd); i++) { - port = this->port; - selected = this->ipv4; - } - if (this->ipv4_natt != -1 && FD_ISSET(this->ipv4_natt, &rfds)) - { - port = this->natt; - selected = this->ipv4_natt; - } - if (this->ipv6 != -1 && FD_ISSET(this->ipv6, &rfds)) - { - port = this->port; - selected = this->ipv6; - } - if (this->ipv6_natt != -1 && FD_ISSET(this->ipv6_natt, &rfds)) - { - port = this->natt; - selected = this->ipv6_natt; + /* To serve all ports with equal priority, we use a round-robin + * scheme to choose the one to process in this invocation */ + index = (rr + i) % countof(pfd); + if (pfd[index].revents & POLLIN) + { + selected = pfd[index].fd; + port = ports[index]; + break; + } } - if (selected) + if (selected != -1) { struct msghdr msg; struct cmsghdr *cmsgptr; diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in index 892549c6c..5c010a59a 100644 --- a/src/libcharon/plugins/socket_dynamic/Makefile.in +++ b/src/libcharon/plugins/socket_dynamic/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in index 88b2ac3f0..0c3bf31b9 100644 --- a/src/libcharon/plugins/socket_win/Makefile.in +++ b/src/libcharon/plugins/socket_win/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in index 3c132457b..f74257af2 100644 --- a/src/libcharon/plugins/sql/Makefile.in +++ b/src/libcharon/plugins/sql/Makefile.in @@ -227,6 +227,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -287,10 +288,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -364,6 +367,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in index d4680186a..a316f5c25 100644 --- a/src/libcharon/plugins/stroke/Makefile.in +++ b/src/libcharon/plugins/stroke/Makefile.in @@ -231,6 +231,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -291,10 +292,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -368,6 +371,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c index 0f3c38986..cd1b4d093 100644 --- a/src/libcharon/plugins/stroke/stroke_attribute.c +++ b/src/libcharon/plugins/stroke/stroke_attribute.c @@ -94,7 +94,7 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name) */ static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id, host_t *requested, - mem_pool_op_t operation) + mem_pool_op_t operation, host_t *peer) { host_t *addr = NULL; enumerator_t *enumerator; @@ -107,7 +107,7 @@ static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools, pool = find_pool(this, name); if (pool) { - addr = pool->acquire_address(pool, id, requested, operation); + addr = pool->acquire_address(pool, id, requested, operation, peer); if (addr) { break; @@ -120,20 +120,24 @@ static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools, } METHOD(attribute_provider_t, acquire_address, host_t*, - private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id, + private_stroke_attribute_t *this, linked_list_t *pools, ike_sa_t *ike_sa, host_t *requested) { - host_t *addr; + identification_t *id; + host_t *addr, *peer; + + id = ike_sa->get_other_eap_id(ike_sa); + peer = ike_sa->get_other_host(ike_sa); this->lock->read_lock(this->lock); - addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING); + addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING, peer); if (!addr) { - addr = find_addr(this, pools, id, requested, MEM_POOL_NEW); + addr = find_addr(this, pools, id, requested, MEM_POOL_NEW, peer); if (!addr) { - addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN); + addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN, peer); } } @@ -144,13 +148,16 @@ METHOD(attribute_provider_t, acquire_address, host_t*, METHOD(attribute_provider_t, release_address, bool, private_stroke_attribute_t *this, linked_list_t *pools, host_t *address, - identification_t *id) + ike_sa_t *ike_sa) { enumerator_t *enumerator; + identification_t *id; mem_pool_t *pool; bool found = FALSE; char *name; + id = ike_sa->get_other_eap_id(ike_sa); + enumerator = pools->create_enumerator(pools); this->lock->read_lock(this->lock); while (enumerator->enumerate(enumerator, &name)) @@ -197,9 +204,8 @@ static bool attr_filter(void *lock, host_t **in, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_stroke_attribute_t *this, linked_list_t *pools, - identification_t *id, linked_list_t *vips) + ike_sa_t *ike_sa, linked_list_t *vips) { - ike_sa_t *ike_sa; peer_cfg_t *peer_cfg; enumerator_t *enumerator; attributes_t *attr; @@ -413,4 +419,3 @@ stroke_attribute_t *stroke_attribute_create() return &this->public; } - diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c index f8026875f..b470b81c6 100644 --- a/src/libcharon/plugins/stroke/stroke_ca.c +++ b/src/libcharon/plugins/stroke/stroke_ca.c @@ -120,6 +120,84 @@ static void ca_section_destroy(ca_section_t *this) } /** + * Data for the certificate enumerator + */ +typedef struct { + private_stroke_ca_t *this; + certificate_type_t cert; + key_type_t key; + identification_t *id; +} cert_data_t; + +/** + * destroy cert_data + */ +static void cert_data_destroy(cert_data_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * filter function for certs enumerator + */ +static bool certs_filter(cert_data_t *data, ca_section_t **in, + certificate_t **out) +{ + public_key_t *public; + certificate_t *cert = (*in)->cert; + + if (data->cert == CERT_ANY || data->cert == cert->get_type(cert)) + { + public = cert->get_public_key(cert); + if (public) + { + if (data->key == KEY_ANY || data->key == public->get_type(public)) + { + if (data->id && public->has_fingerprint(public, + data->id->get_encoding(data->id))) + { + public->destroy(public); + *out = cert; + return TRUE; + } + } + public->destroy(public); + } + else if (data->key != KEY_ANY) + { + return FALSE; + } + if (data->id == NULL || cert->has_subject(cert, data->id)) + { + *out = cert; + return TRUE; + } + } + return FALSE; +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_stroke_ca_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + enumerator_t *enumerator; + cert_data_t *data; + + INIT(data, + .this = this, + .cert = cert, + .key = key, + .id = id, + ); + + this->lock->read_lock(this->lock); + enumerator = this->sections->create_enumerator(this->sections); + return enumerator_create_filter(enumerator, (void*)certs_filter, data, + (void*)cert_data_destroy); +} + +/** * data to pass to create_inner_cdp */ typedef struct { @@ -438,7 +516,7 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred) .public = { .set = { .create_private_enumerator = (void*)return_null, - .create_cert_enumerator = (void*)return_null, + .create_cert_enumerator = _create_cert_enumerator, .create_shared_enumerator = (void*)return_null, .create_cdp_enumerator = _create_cdp_enumerator, .cache_cert = (void*)nop, @@ -456,4 +534,3 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred) return &this->public; } - diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 62967b006..55ec7cdc9 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2014 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -301,7 +301,8 @@ static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy) static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) { enumerator_t *enumerator; - bool rsa = FALSE, ecdsa = FALSE, rsa_len = FALSE, ecdsa_len = FALSE; + bool rsa = FALSE, ecdsa = FALSE, bliss = FALSE, + rsa_len = FALSE, ecdsa_len = FALSE, bliss_strength = FALSE; int strength; char *token; @@ -328,9 +329,12 @@ static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) { "sha256", SIGN_ECDSA_256, KEY_ECDSA, }, { "sha384", SIGN_ECDSA_384, KEY_ECDSA, }, { "sha512", SIGN_ECDSA_521, KEY_ECDSA, }, + { "sha256", SIGN_BLISS_WITH_SHA256, KEY_BLISS, }, + { "sha384", SIGN_BLISS_WITH_SHA384, KEY_BLISS, }, + { "sha512", SIGN_BLISS_WITH_SHA512, KEY_BLISS, }, }; - if (rsa_len || ecdsa_len) + if (rsa_len || ecdsa_len || bliss_strength) { /* expecting a key strength token */ strength = atoi(token); if (strength) @@ -343,8 +347,12 @@ static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) { cfg->add(cfg, AUTH_RULE_ECDSA_STRENGTH, (uintptr_t)strength); } + else if (bliss_strength) + { + cfg->add(cfg, AUTH_RULE_BLISS_STRENGTH, (uintptr_t)strength); + } } - rsa_len = ecdsa_len = FALSE; + rsa_len = ecdsa_len = bliss_strength = FALSE; if (strength) { continue; @@ -360,6 +368,11 @@ static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) ecdsa = ecdsa_len = TRUE; continue; } + if (streq(token, "bliss")) + { + bliss = bliss_strength = TRUE; + continue; + } if (streq(token, "pubkey")) { continue; @@ -376,7 +389,8 @@ static void parse_pubkey_constraints(char *auth, auth_cfg_t *cfg) */ if ((rsa && schemes[i].key == KEY_RSA) || (ecdsa && schemes[i].key == KEY_ECDSA) || - (!rsa && !ecdsa)) + (bliss && schemes[i].key == KEY_BLISS) || + (!rsa && !ecdsa && !bliss)) { cfg->add(cfg, AUTH_RULE_SIGNATURE_SCHEME, (uintptr_t)schemes[i].scheme); @@ -590,7 +604,8 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, /* authentication metod (class, actually) */ if (strpfx(auth, "pubkey") || strpfx(auth, "rsa") || - strpfx(auth, "ecdsa")) + strpfx(auth, "ecdsa") || + strpfx(auth, "bliss")) { cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); build_crl_policy(cfg, local, msg->add_conn.crl_policy); @@ -620,9 +635,16 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, else if (strpfx(auth, "eap")) { eap_vendor_type_t *type; + char *pos; cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); - + /* check for public key constraints for EAP-TLS etc. */ + pos = strchr(auth, ':'); + if (pos) + { + *pos = 0; + parse_pubkey_constraints(pos + 1, cfg); + } type = eap_vendor_type_from_string(auth); if (type) { @@ -667,6 +689,24 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, } /** + * build a mem_pool_t from an address range + */ +static mem_pool_t *create_pool_range(char *str) +{ + mem_pool_t *pool; + host_t *from, *to; + + if (!host_create_from_range(str, &from, &to)) + { + return NULL; + } + pool = mem_pool_create_range(str, from, to); + from->destroy(from); + to->destroy(to); + return pool; +} + +/** * build a peer_cfg from a stroke msg */ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, @@ -789,17 +829,25 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, } else { - /* in-memory pool, named using CIDR notation */ + /* in-memory pool, using range or CIDR notation */ + mem_pool_t *pool; host_t *base; int bits; - base = host_create_from_subnet(token, &bits); - if (base) + pool = create_pool_range(token); + if (!pool) + { + base = host_create_from_subnet(token, &bits); + if (base) + { + pool = mem_pool_create(token, base, bits); + base->destroy(base); + } + } + if (pool) { - this->attributes->add_pool(this->attributes, - mem_pool_create(token, base, bits)); + this->attributes->add_pool(this->attributes, pool); peer_cfg->add_pool(peer_cfg, token); - base->destroy(base); } else { diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index f770d7c9e..0084fbf93 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -352,7 +352,7 @@ METHOD(stroke_control_t, terminate, void, if (streq(name, child_sa->get_name(child_sa))) { child_list->insert_last(child_list, - (void*)(uintptr_t)child_sa->get_reqid(child_sa)); + (void*)(uintptr_t)child_sa->get_unique_id(child_sa)); if (!all) { break; @@ -432,13 +432,13 @@ METHOD(stroke_control_t, rekey, void, while (children->enumerate(children, (void**)&child_sa)) { if ((name && streq(name, child_sa->get_name(child_sa))) || - (id && id == child_sa->get_reqid(child_sa))) + (id && id == child_sa->get_unique_id(child_sa))) { lib->processor->queue_job(lib->processor, (job_t*)rekey_child_sa_job_create( - child_sa->get_reqid(child_sa), child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE))); + child_sa->get_spi(child_sa, TRUE), + ike_sa->get_my_host(ike_sa))); if (!all) { finished = TRUE; diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c index 83431d17c..5e423f1de 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.c +++ b/src/libcharon/plugins/stroke/stroke_cred.c @@ -70,11 +70,21 @@ struct private_stroke_cred_t { char *secrets_file; /** - * credentials + * credentials: end entity certs, attribute certs, CRLs, etc. */ mem_cred_t *creds; /** + * CA certificates + */ + mem_cred_t *cacerts; + + /** + * Attribute Authority certificates + */ + mem_cred_t *aacerts; + + /** * ignore missing CA basic constraint (i.e. treat all certificates in * ipsec.conf ca sections and ipsec.d/cacerts as CA certificates) */ @@ -231,7 +241,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*, } DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", cert->get_subject(cert), filename); - return this->creds->add_cert_ref(this->creds, TRUE, cert); + return this->creds->get_cert_ref(this->creds, cert); } return NULL; } @@ -374,133 +384,183 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*, } /** - * load trusted certificates from a directory + * Load a CA certificate from disk */ -static void load_certdir(private_stroke_cred_t *this, char *path, - certificate_type_t type, x509_flag_t flag) +static void load_x509_ca(private_stroke_cred_t *this, char *file) { - struct stat st; - char *file; - - enumerator_t *enumerator = enumerator_create_directory(path); + certificate_t *cert; - if (!enumerator) + if (this->force_ca_cert) + { /* treat certificate as CA cert even it has no CA basic constraint */ + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, + BUILD_X509_FLAG, X509_CA, BUILD_END); + } + else { - DBG1(DBG_CFG, " reading directory failed"); - return; + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_END); } - - while (enumerator->enumerate(enumerator, NULL, &file, &st)) + if (cert) { - certificate_t *cert; + x509_t *x509 = (x509_t*)cert; - if (!S_ISREG(st.st_mode)) + if (!(x509->get_flags(x509) & X509_CA)) { - /* skip special file */ - continue; + DBG1(DBG_CFG, " ca certificate \"%Y\" lacks ca basic constraint, " + "discarded", cert->get_subject(cert)); + cert->destroy(cert); } - switch (type) + else { - case CERT_X509: - if (flag & X509_CA) - { - if (this->force_ca_cert) - { /* treat this certificate as CA cert even it has no - * CA basic constraint */ - cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_FROM_FILE, file, BUILD_X509_FLAG, - X509_CA, BUILD_END); - } - else - { - cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_FROM_FILE, file, BUILD_END); - } - if (cert) - { - x509_t *x509 = (x509_t*)cert; - - if (!(x509->get_flags(x509) & X509_CA)) - { - DBG1(DBG_CFG, " ca certificate \"%Y\" lacks " - "ca basic constraint, discarded", - cert->get_subject(cert)); - cert->destroy(cert); - cert = NULL; - } - else - { - DBG1(DBG_CFG, " loaded ca certificate \"%Y\" " - "from '%s'", cert->get_subject(cert), file); - } - } - else + DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", + cert->get_subject(cert), file); + this->cacerts->add_cert(this->cacerts, TRUE, cert); + } + } + else + { + DBG1(DBG_CFG, " loading ca certificate from '%s' failed", file); + } +} + +/** + * Load AA certificate with flags from disk + */ +static void load_x509_aa(private_stroke_cred_t *this, char *file) +{ + certificate_t *cert; + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, + BUILD_X509_FLAG, X509_AA, BUILD_END); + if (cert) + { + DBG1(DBG_CFG, " loaded AA certificate \"%Y\" from '%s'", + cert->get_subject(cert), file); + this->aacerts->add_cert(this->aacerts, TRUE, cert); + } + else + { + DBG1(DBG_CFG, " loading AA certificate from '%s' failed", file); + } +} + +/** + * Load a certificate with flags from disk + */ +static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag) +{ + certificate_t *cert; + + /* for all other flags, we add them to the certificate. */ + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, + BUILD_X509_FLAG, flag, BUILD_END); + if (cert) + { + DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", + cert->get_subject(cert), file); + this->creds->add_cert(this->creds, TRUE, cert); + } + else + { + DBG1(DBG_CFG, " loading certificate from '%s' failed", file); + } +} + +/** + * Load a CRL from a file + */ +static void load_x509_crl(private_stroke_cred_t *this, char *file) +{ + certificate_t *cert; + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, + BUILD_FROM_FILE, file, BUILD_END); + if (cert) + { + this->creds->add_crl(this->creds, (crl_t*)cert); + DBG1(DBG_CFG, " loaded crl from '%s'", file); + } + else + { + DBG1(DBG_CFG, " loading crl from '%s' failed", file); + } +} + +/** + * Load an attribute certificate from a file + */ +static void load_x509_ac(private_stroke_cred_t *this, char *file) +{ + certificate_t *cert; + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, + BUILD_FROM_FILE, file, BUILD_END); + if (cert) + { + DBG1(DBG_CFG, " loaded attribute certificate from '%s'", file); + this->creds->add_cert(this->creds, FALSE, cert); + } + else + { + DBG1(DBG_CFG, " loading attribute certificate from '%s' failed", file); + } +} + +/** + * load trusted certificates from a directory + */ +static void load_certdir(private_stroke_cred_t *this, char *path, + certificate_type_t type, x509_flag_t flag) +{ + enumerator_t *enumerator; + struct stat st; + char *file; + + enumerator = enumerator_create_directory(path); + if (enumerator) + { + while (enumerator->enumerate(enumerator, NULL, &file, &st)) + { + if (!S_ISREG(st.st_mode)) + { + /* skip special file */ + continue; + } + switch (type) + { + case CERT_X509: + if (flag & X509_CA) { - DBG1(DBG_CFG, " loading ca certificate from '%s' " - "failed", file); + load_x509_ca(this, file); } - } - else - { /* for all other flags, we add them to the certificate. */ - cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_FROM_FILE, file, - BUILD_X509_FLAG, flag, BUILD_END); - if (cert) + else if (flag & X509_AA) { - DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", - cert->get_subject(cert), file); + load_x509_aa(this, file); } else { - DBG1(DBG_CFG, " loading certificate from '%s' " - "failed", file); + load_x509(this, file, flag); } - } - if (cert) - { - this->creds->add_cert(this->creds, TRUE, cert); - } - break; - case CERT_X509_CRL: - cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_CRL, - BUILD_FROM_FILE, file, - BUILD_END); - if (cert) - { - this->creds->add_crl(this->creds, (crl_t*)cert); - DBG1(DBG_CFG, " loaded crl from '%s'", file); - } - else - { - DBG1(DBG_CFG, " loading crl from '%s' failed", file); - } - break; - case CERT_X509_AC: - cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_AC, - BUILD_FROM_FILE, file, - BUILD_END); - if (cert) - { - this->creds->add_cert(this->creds, FALSE, cert); - DBG1(DBG_CFG, " loaded attribute certificate from '%s'", - file); - } - else - { - DBG1(DBG_CFG, " loading attribute certificate from '%s' " - "failed", file); - } - break; - default: - break; + break; + case CERT_X509_CRL: + load_x509_crl(this, file); + break; + case CERT_X509_AC: + load_x509_ac(this, file); + break; + default: + break; + } } + enumerator->destroy(enumerator); + } + else + { + DBG1(DBG_CFG, " reading directory failed"); } - enumerator->destroy(enumerator); } METHOD(stroke_cred_t, cache_cert, void, @@ -1124,6 +1184,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, while (fetchline(src, &line)) { chunk_t ids, token; + key_type_t key_type; shared_key_type_t type; line_nr++; @@ -1222,10 +1283,22 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, DBG1(DBG_CFG, "line %d: missing token", line_nr); break; } - if (match("RSA", &token) || match("ECDSA", &token)) + if (match("RSA", &token) || match("ECDSA", &token) || + match("BLISS", &token)) { - if (!load_private(secrets, line, line_nr, prompt, - match("RSA", &token) ? KEY_RSA : KEY_ECDSA)) + if (match("RSA", &token)) + { + key_type = KEY_RSA; + } + else if (match("ECDSA", &token)) + { + key_type = KEY_ECDSA; + } + else + { + key_type = KEY_BLISS; + } + if (!load_private(secrets, line, line_nr, prompt, key_type)) { break; } @@ -1256,8 +1329,8 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, } else { - DBG1(DBG_CFG, "line %d: token must be either " - "RSA, ECDSA, P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr); + DBG1(DBG_CFG, "line %d: token must be either RSA, ECDSA, BLISS, " + "P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr); break; } } @@ -1308,6 +1381,8 @@ METHOD(stroke_cred_t, reread, void, { DBG1(DBG_CFG, "rereading ca certificates from '%s'", CA_CERTIFICATE_DIR); + this->cacerts->clear(this->cacerts); + lib->credmgr->flush_cache(lib->credmgr, CERT_X509); load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA); } if (msg->reread.flags & REREAD_OCSPCERTS) @@ -1321,6 +1396,8 @@ METHOD(stroke_cred_t, reread, void, { DBG1(DBG_CFG, "rereading aa certificates from '%s'", AA_CERTIFICATE_DIR); + this->aacerts->clear(this->aacerts); + lib->credmgr->flush_cache(lib->credmgr, CERT_X509); load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA); } if (msg->reread.flags & REREAD_ACERTS) @@ -1346,7 +1423,11 @@ METHOD(stroke_cred_t, add_shared, void, METHOD(stroke_cred_t, destroy, void, private_stroke_cred_t *this) { + lib->credmgr->remove_set(lib->credmgr, &this->aacerts->set); + lib->credmgr->remove_set(lib->credmgr, &this->cacerts->set); lib->credmgr->remove_set(lib->credmgr, &this->creds->set); + this->aacerts->destroy(this->aacerts); + this->cacerts->destroy(this->cacerts); this->creds->destroy(this->creds); free(this); } @@ -1379,9 +1460,13 @@ stroke_cred_t *stroke_cred_create() "%s.plugins.stroke.secrets_file", SECRETS_FILE, lib->ns), .creds = mem_cred_create(), + .cacerts = mem_cred_create(), + .aacerts = mem_cred_create(), ); lib->credmgr->add_set(lib->credmgr, &this->creds->set); + lib->credmgr->add_set(lib->credmgr, &this->cacerts->set); + lib->credmgr->add_set(lib->credmgr, &this->aacerts->set); this->force_ca_cert = lib->settings->get_bool(lib->settings, "%s.plugins.stroke.ignore_missing_ca_basic_constraint", diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h index f6fbb96d3..9434629ef 100644 --- a/src/libcharon/plugins/stroke/stroke_cred.h +++ b/src/libcharon/plugins/stroke/stroke_cred.h @@ -50,10 +50,13 @@ struct stroke_cred_t { void (*reread)(stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt); /** - * Load a CA certificate, and serve it through the credential_set. + * Load a CA certificate. + * + * This method does not add the loaded CA certificate to the internal + * credentail set, but returns it only. * * @param filename file to load CA cert from - * @return reference to loaded certificate, or NULL + * @return loaded certificate, or NULL */ certificate_t* (*load_ca)(stroke_cred_t *this, char *filename); diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c index fef8cab67..d0cc9afab 100644 --- a/src/libcharon/plugins/stroke/stroke_handler.c +++ b/src/libcharon/plugins/stroke/stroke_handler.c @@ -94,10 +94,9 @@ static bool attr_filter(void *lock, host_t **in, } METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, - private_stroke_handler_t *this, identification_t *server, + private_stroke_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips) { - ike_sa_t *ike_sa; peer_cfg_t *peer_cfg; enumerator_t *enumerator; attributes_t *attr; diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index 1aa49ce0d..68b8232bc 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -214,11 +214,12 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) config = child_sa->get_config(child_sa); now = time_monotonic(NULL); - fprintf(out, "%12s{%d}: %N, %N%s", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + fprintf(out, "%12s{%d}: %N, %N%s, reqid %u", + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), child_sa_state_names, child_sa->get_state(child_sa), ipsec_mode_names, child_sa->get_mode(child_sa), - config->use_proxy_mode(config) ? "_PROXY" : ""); + config->use_proxy_mode(config) ? "_PROXY" : "", + child_sa->get_reqid(child_sa)); if (child_sa->get_state(child_sa) == CHILD_INSTALLED) { @@ -238,7 +239,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) if (all) { fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa), - child_sa->get_reqid(child_sa)); + child_sa->get_unique_id(child_sa)); proposal = child_sa->get_proposal(child_sa); if (proposal) @@ -322,7 +323,8 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) } } - else if (child_sa->get_state(child_sa) == CHILD_REKEYING) + else if (child_sa->get_state(child_sa) == CHILD_REKEYING || + child_sa->get_state(child_sa) == CHILD_REKEYED) { rekey = child_sa->get_lifetime(child_sa, TRUE); fprintf(out, ", expires in %V", &now, &rekey); @@ -333,7 +335,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) other_ts = linked_list_create_from_enumerator( child_sa->create_ts_enumerator(child_sa, FALSE)); fprintf(out, "\n%12s{%d}: %#R=== %#R\n", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), my_ts, other_ts); my_ts->destroy(my_ts); other_ts->destroy(other_ts); @@ -496,7 +498,7 @@ METHOD(stroke_list_t, status, void, { struct mallinfo mi = mallinfo(); - fprintf(out, " malloc: sbrk %d, mmap %d, used %d, free %d\n", + fprintf(out, " malloc: sbrk %u, mmap %u, used %u, free %u\n", mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks); } #endif /* HAVE_MALLINFO */ diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c index 31df1f99b..f64b99f08 100644 --- a/src/libcharon/plugins/stroke/stroke_plugin.c +++ b/src/libcharon/plugins/stroke/stroke_plugin.c @@ -69,6 +69,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_SDEPEND(PRIVKEY, KEY_RSA), PLUGIN_SDEPEND(PRIVKEY, KEY_ECDSA), PLUGIN_SDEPEND(PRIVKEY, KEY_DSA), + PLUGIN_SDEPEND(PRIVKEY, KEY_BLISS), PLUGIN_SDEPEND(CERT_DECODE, CERT_ANY), PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), PLUGIN_SDEPEND(CERT_DECODE, CERT_X509_CRL), diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 54dd56e91..db7e66f14 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -24,7 +24,6 @@ #include <unistd.h> #include <errno.h> -#include <hydra.h> #include <daemon.h> #include "stroke_config.h" @@ -747,8 +746,10 @@ METHOD(stroke_socket_t, destroy, void, 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); - hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); + charon->attributes->remove_provider(charon->attributes, + &this->attribute->provider); + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); charon->bus->remove_listener(charon->bus, &this->counter->listener); this->cred->destroy(this->cred); this->ca->destroy(this->ca); @@ -790,8 +791,10 @@ stroke_socket_t *stroke_socket_create() 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); - hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); + charon->attributes->add_provider(charon->attributes, + &this->attribute->provider); + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); charon->bus->add_listener(charon->bus, &this->counter->listener); max_concurrent = lib->settings->get_int(lib->settings, diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in index 0e477f9f3..be148b6c3 100644 --- a/src/libcharon/plugins/systime_fix/Makefile.in +++ b/src/libcharon/plugins/systime_fix/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in index 3f2952c4b..17cc341c5 100644 --- a/src/libcharon/plugins/tnc_ifmap/Makefile.in +++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in @@ -232,6 +232,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -292,10 +293,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -369,6 +372,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in index 97c479632..ef05275b7 100644 --- a/src/libcharon/plugins/tnc_pdp/Makefile.in +++ b/src/libcharon/plugins/tnc_pdp/Makefile.in @@ -233,6 +233,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -293,10 +294,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -370,6 +373,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c index 109c216d5..91456f8da 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Andreas Steffen + * Copyright (C) 2012-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -646,8 +646,8 @@ static bool pt_tls_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even int pt_tls_fd; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); - identification_t *peer; - host_t *host; + identification_t *client_id; + host_t *server_ip, *client_ip; pt_tls_server_t *pt_tls; tnccs_t *tnccs; pt_tls_auth_t auth = PT_TLS_AUTH_TLS_OR_SASL; @@ -658,17 +658,22 @@ static bool pt_tls_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even DBG1(DBG_TNC, "accepting PT-TLS stream failed: %s", strerror(errno)); return FALSE; } - host = host_create_from_sockaddr((sockaddr_t*)&addr); - DBG1(DBG_TNC, "accepting PT-TLS stream from %H", host); - host->destroy(host); + client_ip = host_create_from_sockaddr((sockaddr_t*)&addr); + DBG1(DBG_TNC, "accepting PT-TLS stream from %H", client_ip); + + /* Currently we do not determine the IP address of the server interface */ + server_ip = host_create_any(client_ip->get_family(client_ip)); - /* At this moment the peer identity is not known yet */ - peer = identification_create_from_encoding(ID_ANY, chunk_empty), + /* At this moment the client identity is not known yet */ + client_id = identification_create_from_encoding(ID_ANY, chunk_empty), tnccs = tnc->tnccs->create_instance(tnc->tnccs, TNCCS_2_0, TRUE, - this->server, peer, TNC_IFT_TLS_2_0, + this->server, client_id, server_ip, + client_ip, TNC_IFT_TLS_2_0, (tnccs_cb_t)get_recommendation); - peer->destroy(peer); + client_id->destroy(client_id); + server_ip->destroy(server_ip); + client_ip->destroy(client_ip); if (!tnccs) { diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in index 5e16c3c35..2c031383a 100644 --- a/src/libcharon/plugins/uci/Makefile.in +++ b/src/libcharon/plugins/uci/Makefile.in @@ -227,6 +227,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -287,10 +288,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -364,6 +367,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am deleted file mode 100644 index b7f8fc319..000000000 --- a/src/libcharon/plugins/unit_tester/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/libstrongswan \ - -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = \ - $(PLUGIN_CFLAGS) - -if MONOLITHIC -noinst_LTLIBRARIES = libstrongswan-unit-tester.la -else -plugin_LTLIBRARIES = libstrongswan-unit-tester.la -endif - -libstrongswan_unit_tester_la_SOURCES = \ - unit_tester.c unit_tester.h tests.h \ - tests/test_auth_info.c \ - tests/test_curl.c \ - tests/test_mysql.c \ - tests/test_sqlite.c \ - tests/test_cert.c \ - tests/test_med_db.c \ - tests/test_pool.c \ - tests/test_agent.c - -libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/unit_tester/tests/test_agent.c b/src/libcharon/plugins/unit_tester/tests/test_agent.c deleted file mode 100644 index baab629be..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_agent.c +++ /dev/null @@ -1,67 +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 <library.h> -#include <daemon.h> - -/******************************************************************************* - * SSH agent signature creation and verification - ******************************************************************************/ -bool test_agent() -{ - char *path; - chunk_t sig, data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08); - private_key_t *private; - public_key_t *public; - - path = getenv("SSH_AUTH_SOCK"); - if (!path) - { - DBG1(DBG_CFG, "ssh-agent not found."); - return FALSE; - } - - private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, - BUILD_AGENT_SOCKET, path, BUILD_END); - if (!private) - { - return FALSE; - } - if (!private->sign(private, SIGN_RSA_EMSA_PKCS1_SHA1, data, &sig)) - { - return FALSE; - } - public = private->get_public_key(private); - if (!public) - { - return FALSE;; - } - if (!public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig)) - { - return FALSE; - } - free(sig.ptr); - data.ptr[1] = 0x01; /* fake it */ - if (public->verify(public, SIGN_RSA_EMSA_PKCS1_SHA1, data, sig)) - { - return FALSE; - } - - private->destroy(private); - public->destroy(public); - - return TRUE; -} - diff --git a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c deleted file mode 100644 index c250c356f..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c +++ /dev/null @@ -1,140 +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 <daemon.h> -#include <library.h> -#include <credentials/auth_cfg.h> - - -static chunk_t certchunk = chunk_from_chars( - 0x30,0x82,0x02,0xfa,0x30,0x82,0x01,0xe2,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x5a, - 0xf2,0x65,0xae,0x78,0xff,0x23,0xde,0xf7,0xa6,0xa3,0x94,0x8c,0x3f,0xa0,0xc1,0x30, - 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x39, - 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30, - 0x17,0x06,0x03,0x55,0x04,0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74, - 0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04, - 0x03,0x13,0x06,0x6d,0x61,0x72,0x74,0x69,0x6e,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30, - 0x34,0x32,0x37,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x17,0x0d,0x31,0x32,0x30,0x34, - 0x32,0x35,0x30,0x37,0x31,0x34,0x32,0x36,0x5a,0x30,0x39,0x31,0x0b,0x30,0x09,0x06, - 0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04, - 0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53, - 0x77,0x61,0x6e,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x03,0x13,0x06,0x6d,0x61, - 0x72,0x74,0x69,0x6e,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86, - 0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a, - 0x02,0x82,0x01,0x01,0x00,0xd7,0xb9,0xba,0x4d,0xe2,0x3b,0x3d,0x35,0x7a,0x3f,0x88, - 0x67,0x95,0xe7,0xfd,0x9f,0xe9,0x0a,0x0d,0x79,0x3a,0x9e,0x21,0x8f,0xcb,0xe4,0x67, - 0x24,0xae,0x0c,0xda,0xb3,0xcc,0xec,0x36,0xb4,0xa8,0x4d,0xf1,0x3d,0xad,0xe4,0x8c, - 0x63,0x92,0x54,0xb7,0xb2,0x02,0xa2,0x00,0x62,0x8b,0x04,0xac,0xa0,0x17,0xad,0x17, - 0x9a,0x05,0x0d,0xd7,0xb3,0x08,0x02,0xc5,0x26,0xcf,0xdd,0x05,0x42,0xfc,0x13,0x6d, - 0x9f,0xb1,0xf3,0x4f,0x82,0x1d,0xef,0x01,0xc9,0x91,0xea,0x37,0x1b,0x79,0x28,0xfa, - 0xbf,0x9f,0xb3,0xeb,0x82,0x4f,0x10,0xc6,0x4b,0xa4,0x08,0xf7,0x8e,0xf2,0x00,0xea, - 0x04,0x97,0x80,0x9f,0x65,0x86,0xde,0x6b,0xc7,0xda,0x83,0xfc,0xad,0x4a,0xaf,0x52, - 0x8b,0x4d,0x33,0xee,0x49,0x87,0x2f,0x3b,0x60,0x45,0x66,0x8f,0xe6,0x89,0xcc,0xb1, - 0x92,0x02,0x17,0x2b,0x7b,0x8e,0x90,0x47,0x84,0x84,0x59,0x95,0x81,0xd8,0xe0,0xf3, - 0x87,0xe0,0x04,0x09,0xfd,0xcc,0x3a,0x21,0x34,0xfa,0xec,0xbe,0xf5,0x9c,0xcf,0x55, - 0x80,0x7b,0xe3,0x75,0x9d,0x36,0x68,0xab,0x83,0xe3,0xad,0x01,0x53,0x0d,0x8a,0x9a, - 0xa6,0xb0,0x15,0xc9,0xc5,0xf8,0x9b,0x51,0x32,0xcf,0x97,0x6c,0xfe,0x4a,0x56,0x3c, - 0xc8,0x8f,0x4a,0x70,0x23,0x4f,0xf6,0xf7,0xe6,0x9f,0x09,0xcd,0x8f,0xea,0x20,0x7d, - 0x34,0xc0,0xc5,0xc0,0x34,0x06,0x6f,0x8b,0xeb,0x04,0x54,0x3f,0x0e,0xcd,0xe2,0x85, - 0xab,0x94,0x3e,0x91,0x6c,0x18,0x6f,0x96,0x5d,0xf2,0x8b,0x10,0xe9,0x90,0x43,0xb0, - 0x61,0x52,0xac,0xcf,0x75,0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86, - 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x09,0x63, - 0x42,0xad,0xe5,0xa3,0xf6,0xc9,0x5d,0x08,0xf2,0x78,0x7b,0xeb,0x8a,0xef,0x50,0x00, - 0xc8,0xeb,0xe9,0x26,0x94,0xcb,0x84,0x10,0x7e,0x42,0x6b,0x86,0x38,0x57,0xa6,0x02, - 0x98,0x5a,0x2c,0x8f,0x44,0x32,0x1b,0x97,0x8c,0x7e,0x4b,0xd8,0xe8,0xe8,0x0f,0x4a, - 0xb9,0x31,0x9f,0xf6,0x9f,0x0e,0x67,0x26,0x05,0x2a,0x99,0x14,0x35,0x41,0x47,0x9a, - 0xfa,0x12,0x94,0x0b,0xe9,0x27,0x7c,0x71,0x20,0xd7,0x8d,0x3b,0x97,0x19,0x2d,0x15, - 0xff,0xa4,0xf3,0x89,0x8d,0x29,0x5f,0xf6,0x3f,0x93,0xaf,0x78,0x61,0xe4,0xe1,0x2e, - 0x75,0xc1,0x2c,0xc4,0x76,0x95,0x19,0xf8,0x37,0xdc,0xd8,0x00,0x7a,0x3c,0x0f,0x49, - 0x2e,0x88,0x09,0x16,0xb3,0x92,0x33,0xdf,0x77,0x83,0x4f,0xb5,0x9e,0x30,0x8c,0x48, - 0x1d,0xd8,0x84,0xfb,0xf1,0xb9,0xa0,0xbe,0x25,0xff,0x4c,0xeb,0xef,0x2b,0xcd,0xfa, - 0x0b,0x94,0x66,0x3b,0x28,0x08,0x3f,0x3a,0xda,0x41,0xd0,0x6b,0xab,0x5e,0xbb,0x8a, - 0x9f,0xdc,0x98,0x3e,0x59,0x37,0x48,0xbe,0x69,0xde,0x85,0x82,0xf2,0x53,0x8b,0xe4, - 0x44,0xe4,0x71,0x91,0x14,0x85,0x0e,0x1e,0x79,0xdd,0x62,0xf5,0xdc,0x25,0x89,0xab, - 0x50,0x5b,0xaa,0xae,0xe3,0x64,0x6a,0x23,0x34,0xd7,0x30,0xe2,0x2a,0xc8,0x81,0x0c, - 0xec,0xd2,0x31,0xc6,0x1e,0xb6,0xc0,0x57,0xd9,0xe1,0x14,0x06,0x9b,0xf8,0x51,0x69, - 0x47,0xf0,0x9c,0xcd,0x69,0xef,0x8e,0x5f,0x62,0xda,0x10,0xf7,0x3c,0x6d,0x0f,0x33, - 0xec,0x6f,0xfd,0x94,0x07,0x16,0x41,0x32,0x06,0xa4,0xe1,0x08,0x31,0x87, -); - -/******************************************************************************* - * auth info test - ******************************************************************************/ -bool test_auth_cfg() -{ - auth_cfg_t *auth = auth_cfg_create(), *auth2; - certificate_t *c1, *c2; - enumerator_t *enumerator; - int round = 0; - void *value; - auth_rule_t type; - - c1 = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, certchunk, - BUILD_END); - if (!c1) - { - return FALSE; - } - - auth->add(auth, AUTH_RULE_SUBJECT_CERT, c1->get_ref(c1)); - c2 = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (!c2) - { - return FALSE; - } - if (!c1->equals(c1, c2)) - { - return FALSE; - } - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &value)) - { - round++; - if (round == 1 && type == AUTH_RULE_SUBJECT_CERT && value == c1) - { - continue; - } - return FALSE; - } - enumerator->destroy(enumerator); - - auth2 = auth_cfg_create(); - auth2->add(auth2, AUTH_RULE_CA_CERT, c1->get_ref(c1)); - auth2->merge(auth2, auth, FALSE); - - round = 0; - enumerator = auth2->create_enumerator(auth2); - while (enumerator->enumerate(enumerator, &type, &value)) - { - round++; - if (round == 1 && type == AUTH_RULE_CA_CERT && value == c1) - { - continue; - } - if (round == 2 && type == AUTH_RULE_SUBJECT_CERT && value == c1) - { - continue; - } - return FALSE; - } - enumerator->destroy(enumerator); - auth->destroy(auth); - auth2->destroy(auth2); - c1->destroy(c1); - return TRUE; -} - diff --git a/src/libcharon/plugins/unit_tester/tests/test_cert.c b/src/libcharon/plugins/unit_tester/tests/test_cert.c deleted file mode 100644 index f4410a688..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_cert.c +++ /dev/null @@ -1,108 +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 <library.h> -#include <daemon.h> -#include <credentials/certificates/x509.h> - -/******************************************************************************* - * X509 certificate generation and parsing - ******************************************************************************/ -bool test_cert_x509() -{ - private_key_t *ca_key, *peer_key; - public_key_t *public; - certificate_t *ca_cert, *peer_cert, *parsed; - identification_t *issuer, *subject; - u_int32_t serial = htonl(0); - chunk_t encoding; - - issuer = identification_create_from_string("CN=CA, OU=Test, O=strongSwan"); - subject = identification_create_from_string("CN=Peer, OU=Test, O=strongSwan"); - - ca_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, - BUILD_KEY_SIZE, 1024, BUILD_END); - peer_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, - BUILD_KEY_SIZE, 1024, BUILD_END); - if (!ca_key) - { - return FALSE; - } - ca_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_SIGNING_KEY, ca_key, - BUILD_SUBJECT, issuer, - BUILD_SERIAL, chunk_from_thing(serial), - BUILD_X509_FLAG, X509_CA, - BUILD_END); - if (!ca_cert) - { - return FALSE; - } - - ca_cert->get_encoding(ca_cert, CERT_ASN1_DER, &encoding); - parsed = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, encoding, - BUILD_END); - chunk_free(&encoding); - if (!parsed) - { - return FALSE; - } - if (!parsed->issued_by(parsed, ca_cert, NULL)) - { - return FALSE; - } - parsed->destroy(parsed); - - serial = htonl(ntohl(serial) + 1); - public = peer_key->get_public_key(peer_key); - peer_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_SIGNING_KEY, ca_key, - BUILD_SIGNING_CERT, ca_cert, - BUILD_PUBLIC_KEY, public, - BUILD_SUBJECT, subject, - BUILD_SERIAL, chunk_from_thing(serial), - BUILD_END); - public->destroy(public); - if (!peer_cert) - { - return FALSE; - } - - peer_cert->get_encoding(peer_cert, CERT_ASN1_DER, &encoding); - parsed = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, encoding, - BUILD_END); - chunk_free(&encoding); - if (!parsed) - { - return FALSE; - } - if (!parsed->issued_by(parsed, ca_cert, NULL)) - { - return FALSE; - } - parsed->destroy(parsed); - - ca_cert->destroy(ca_cert); - ca_key->destroy(ca_key); - peer_cert->destroy(peer_cert); - peer_key->destroy(peer_key); - issuer->destroy(issuer); - subject->destroy(subject); - return TRUE; -} - - diff --git a/src/libcharon/plugins/unit_tester/tests/test_curl.c b/src/libcharon/plugins/unit_tester/tests/test_curl.c deleted file mode 100644 index 21656a94e..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_curl.c +++ /dev/null @@ -1,44 +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 <daemon.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> - -/******************************************************************************* - * curl get test - ******************************************************************************/ - -bool test_curl_get() -{ - chunk_t chunk; - - if (lib->fetcher->fetch(lib->fetcher, "http://www.strongswan.org", - &chunk, FETCH_END) != SUCCESS) - { - return FALSE; - } - free(chunk.ptr); - - if (lib->fetcher->fetch(lib->fetcher, "http://www.google.com", - &chunk, FETCH_END) != SUCCESS) - { - return FALSE; - } - free(chunk.ptr); - 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 deleted file mode 100644 index 75244ab8f..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_med_db.c +++ /dev/null @@ -1,54 +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 <library.h> -#include <daemon.h> -#include <collections/enumerator.h> - -#include <unistd.h> - -/******************************************************************************* - * fetch public key from mediation database - ******************************************************************************/ - -bool test_med_db() -{ - chunk_t found, keyid = chunk_from_chars( - 0xed,0x90,0xe6,0x4f,0xec,0xa2,0x1f,0x4b, - 0x68,0x97,0x99,0x24,0x22,0xe0,0xde,0x21, - 0xb9,0xd6,0x26,0x29 - ); - identification_t *id; - enumerator_t *enumerator; - public_key_t *public; - auth_cfg_t *auth; - bool good = FALSE; - - id = identification_create_from_encoding(ID_KEY_ID, keyid); - enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, - KEY_ANY, id, NULL); - while (enumerator->enumerate(enumerator, &public, &auth)) - { - good = public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &found); - if (good) - { - good = chunk_equals(id->get_encoding(id), found); - } - } - enumerator->destroy(enumerator); - id->destroy(id); - return good; -} - diff --git a/src/libcharon/plugins/unit_tester/tests/test_mysql.c b/src/libcharon/plugins/unit_tester/tests/test_mysql.c deleted file mode 100644 index eda238623..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_mysql.c +++ /dev/null @@ -1,89 +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 <library.h> -#include <daemon.h> -#include <collections/enumerator.h> - -/******************************************************************************* - * mysql simple test - ******************************************************************************/ -bool test_mysql() -{ - database_t *db; - char *txt = "I'm a superduper test"; - chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08); - int row; - chunk_t qdata; - char *qtxt; - bool good = FALSE; - enumerator_t *enumerator; - - db = lib->db->create(lib->db, "mysql://testuser:testpass@localhost/test"); - if (!db) - { - return FALSE; - } - if (db->execute(db, NULL, "CREATE TABLE test (" - "id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, " - "txt TEXT, data BLOB)") < 0) - { - return FALSE; - } - if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)", - DB_TEXT, txt, DB_BLOB, data) < 0) - { - return FALSE; - } - if (row != 1) - { - return FALSE; - } - enumerator = db->query(db, "SELECT txt, data FROM test WHERE id = ?", - DB_INT, row, - DB_TEXT, DB_BLOB); - if (!enumerator) - { - return FALSE; - } - while (enumerator->enumerate(enumerator, &qtxt, &qdata)) - { - if (good) - { /* only one row */ - good = FALSE; - break; - } - if (streq(qtxt, txt) && chunk_equals(data, qdata)) - { - good = TRUE; - } - } - enumerator->destroy(enumerator); - if (!good) - { - return FALSE; - } - if (db->execute(db, NULL, "DELETE FROM test WHERE id = ?", DB_INT, row) != 1) - { - return FALSE; - } - if (db->execute(db, NULL, "DROP TABLE test") < 0) - { - return FALSE; - } - db->destroy(db); - return TRUE; -} - diff --git a/src/libcharon/plugins/unit_tester/tests/test_pool.c b/src/libcharon/plugins/unit_tester/tests/test_pool.c deleted file mode 100644 index f36953f3a..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_pool.c +++ /dev/null @@ -1,100 +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 <time.h> - -#include <library.h> -#include <threading/thread.h> -#include <hydra.h> - -#define ALLOCS 1000 -#define THREADS 20 - -static void* testing(void *thread) -{ - int i; - host_t *addr[ALLOCS]; - identification_t *id[ALLOCS]; - linked_list_t *pools; - - /* prepare identities */ - for (i = 0; i < ALLOCS; i++) - { - char buf[256]; - - snprintf(buf, sizeof(buf), "%d-%d@strongswan.org", (uintptr_t)thread, i); - id[i] = identification_create_from_string(buf); - } - - pools = linked_list_create(); - pools->insert_last(pools, "test"); - - /* allocate addresses */ - for (i = 0; i < ALLOCS; i++) - { - addr[i] = hydra->attributes->acquire_address(hydra->attributes, - pools, id[i], NULL); - if (!addr[i]) - { - pools->destroy(pools); - return (void*)FALSE; - } - } - - /* release addresses */ - for (i = 0; i < ALLOCS; i++) - { - hydra->attributes->release_address(hydra->attributes, - pools, addr[i], id[i]); - } - - pools->destroy(pools); - - /* cleanup */ - for (i = 0; i < ALLOCS; i++) - { - addr[i]->destroy(addr[i]); - id[i]->destroy(id[i]); - } - return (void*)TRUE; -} - - -/******************************************************************************* - * SQL pool performance test - ******************************************************************************/ -bool test_pool() -{ - thread_t *threads[THREADS]; - uintptr_t i; - - for (i = 0; i < THREADS; i++) - { - if (!(threads[i] = thread_create((thread_main_t)testing, (void*)i))) - { - return FALSE; - } - } - for (i = 0; i < THREADS; i++) - { - bool *res = threads[i]->join(threads[i]); - if (!res) - { - return FALSE; - } - } - return TRUE; -} - diff --git a/src/libcharon/plugins/unit_tester/tests/test_sqlite.c b/src/libcharon/plugins/unit_tester/tests/test_sqlite.c deleted file mode 100644 index 99490b566..000000000 --- a/src/libcharon/plugins/unit_tester/tests/test_sqlite.c +++ /dev/null @@ -1,93 +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 <library.h> -#include <daemon.h> -#include <collections/enumerator.h> - -#include <unistd.h> - - -#define DBFILE "/tmp/strongswan-test.db" - -/******************************************************************************* - * sqlite simple test - ******************************************************************************/ -bool test_sqlite() -{ - database_t *db; - char *txt = "I'm a superduper test"; - chunk_t data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08); - int row; - chunk_t qdata; - char *qtxt; - bool good = FALSE; - enumerator_t *enumerator; - - db = lib->db->create(lib->db, "sqlite://" DBFILE); - if (!db) - { - return FALSE; - } - if (db->execute(db, NULL, "CREATE TABLE test (txt TEXT, data BLOB)") < 0) - { - return FALSE; - } - if (db->execute(db, &row, "INSERT INTO test (txt, data) VALUES (?,?)", - DB_TEXT, txt, DB_BLOB, data) < 0) - { - return FALSE; - } - if (row != 1) - { - return FALSE; - } - enumerator = db->query(db, "SELECT txt, data FROM test WHERE oid = ?", - DB_INT, row, - DB_TEXT, DB_BLOB); - if (!enumerator) - { - return FALSE; - } - while (enumerator->enumerate(enumerator, &qtxt, &qdata)) - { - if (good) - { /* only one row */ - good = FALSE; - break; - } - if (streq(qtxt, txt) && chunk_equals(data, qdata)) - { - good = TRUE; - } - } - enumerator->destroy(enumerator); - if (!good) - { - return FALSE; - } - if (db->execute(db, NULL, "DELETE FROM test WHERE oid = ?", DB_INT, row) != 1) - { - return FALSE; - } - if (db->execute(db, NULL, "DROP TABLE test") < 0) - { - return FALSE; - } - db->destroy(db); - unlink(DBFILE); - return TRUE; -} - diff --git a/src/libcharon/plugins/unit_tester/unit_tester.c b/src/libcharon/plugins/unit_tester/unit_tester.c deleted file mode 100644 index ea7ffca04..000000000 --- a/src/libcharon/plugins/unit_tester/unit_tester.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2013 Tobias Brunner - * 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 "unit_tester.h" - -#include <daemon.h> - -typedef struct private_unit_tester_t private_unit_tester_t; -typedef struct unit_test_t unit_test_t; -typedef enum test_status_t test_status_t; - -/** - * private data of unit_tester - */ -struct private_unit_tester_t { - - /** - * public functions - */ - unit_tester_t public; -}; - -struct unit_test_t { - - /** - * name of the test - */ - char *name; - - /** - * test function - */ - bool (*test)(void); - - /** - * run the test? - */ - bool enabled; -}; - -#undef DEFINE_TEST -#define DEFINE_TEST(name, function, enabled) bool function(); -#include <plugins/unit_tester/tests.h> -#undef DEFINE_TEST -#define DEFINE_TEST(name, function, enabled) {name, function, enabled}, -static unit_test_t tests[] = { -#include <plugins/unit_tester/tests.h> -}; - -static void run_tests(private_unit_tester_t *this) -{ - int i, run = 0, failed = 0, success = 0, skipped = 0; - - DBG1(DBG_CFG, "running unit tests, %d tests registered", - sizeof(tests)/sizeof(unit_test_t)); - - for (i = 0; i < sizeof(tests)/sizeof(unit_test_t); i++) - { - if (tests[i].enabled) - { - run++; - if (tests[i].test()) - { - DBG1(DBG_CFG, "test '%s' successful", tests[i].name); - success++; - } - else - { - DBG1(DBG_CFG, "test '%s' failed", tests[i].name); - failed++; - } - } - else - { - DBG1(DBG_CFG, "test '%s' disabled", tests[i].name); - skipped++; - } - } - DBG1(DBG_CFG, "%d/%d tests successful (%d failed, %d disabled)", - success, run, failed, skipped); -} - -METHOD(plugin_t, get_name, char*, - private_unit_tester_t *this) -{ - return "unit-tester"; -} - -/** - * We currently don't depend explicitly on any plugin features. But in case - * activated tests depend on such features we at least try to run them in plugin - * order. - */ -static bool plugin_cb(private_unit_tester_t *this, - plugin_feature_t *feature, bool reg, void *cb_data) -{ - if (reg) - { - run_tests(this); - } - return TRUE; -} - -METHOD(plugin_t, get_features, int, - private_unit_tester_t *this, plugin_feature_t *features[]) -{ - static plugin_feature_t f[] = { - PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), - PLUGIN_PROVIDE(CUSTOM, "unit-tester"), - }; - *features = f; - return countof(f); -} - -METHOD(plugin_t, destroy, void, - private_unit_tester_t *this) -{ - free(this); -} - -/* - * see header file - */ -plugin_t *unit_tester_plugin_create() -{ - private_unit_tester_t *this; - - INIT(this, - .public = { - .plugin = { - .get_name = _get_name, - .get_features = _get_features, - .destroy = _destroy, - }, - }, - ); - - return &this->public.plugin; -} diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in index 1e04ebced..4f0a7e736 100644 --- a/src/libcharon/plugins/unity/Makefile.in +++ b/src/libcharon/plugins/unity/Makefile.in @@ -228,6 +228,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -288,10 +289,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -365,6 +368,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c index bcef0dc25..9fc9be61a 100644 --- a/src/libcharon/plugins/unity/unity_handler.c +++ b/src/libcharon/plugins/unity/unity_handler.c @@ -50,8 +50,8 @@ struct private_unity_handler_t { * Traffic selector entry for networks to include under a given IKE_SA */ typedef struct { - /** associated IKE_SA, unique ID */ - u_int32_t sa; + /** associated IKE_SA COOKIEs */ + ike_sa_id_t *id; /** traffic selector to include/exclude */ traffic_selector_t *ts; } entry_t; @@ -61,6 +61,7 @@ typedef struct { */ static void entry_destroy(entry_t *this) { + this->id->destroy(this->id); this->ts->destroy(this->ts); free(this); } @@ -131,9 +132,10 @@ static bool add_include(private_unity_handler_t *this, chunk_t data) while (list->remove_first(list, (void**)&ts) == SUCCESS) { INIT(entry, - .sa = ike_sa->get_unique_id(ike_sa), + .id = ike_sa->get_id(ike_sa), .ts = ts, ); + entry->id = entry->id->clone(entry->id); this->mutex->lock(this->mutex); this->include->insert_last(this->include, entry); @@ -171,7 +173,7 @@ static bool remove_include(private_unity_handler_t *this, chunk_t data) enumerator = this->include->create_enumerator(this->include); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->sa == ike_sa->get_unique_id(ike_sa) && + if (entry->id->equals(entry->id, ike_sa->get_id(ike_sa)) && ts->equals(ts, entry->ts)) { this->include->remove_at(this->include, enumerator); @@ -209,8 +211,7 @@ static job_requeue_t add_exclude_async(entry_t *entry) char name[128]; host_t *host; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - entry->sa, FALSE); + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, entry->id); if (ike_sa) { create_shunt_name(ike_sa, entry->ts, name, sizeof(name)); @@ -267,9 +268,10 @@ static bool add_exclude(private_unity_handler_t *this, chunk_t data) while (list->remove_first(list, (void**)&ts) == SUCCESS) { INIT(entry, - .sa = ike_sa->get_unique_id(ike_sa), + .id = ike_sa->get_id(ike_sa), .ts = ts, ); + entry->id = entry->id->clone(entry->id); /* we can't install the shunt policy yet, as we don't know the virtual IP. * Defer installation using an async callback. */ @@ -315,7 +317,7 @@ static bool remove_exclude(private_unity_handler_t *this, chunk_t data) } METHOD(attribute_handler_t, handle, bool, - private_unity_handler_t *this, identification_t *id, + private_unity_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -330,7 +332,7 @@ METHOD(attribute_handler_t, handle, bool, } METHOD(attribute_handler_t, release, void, - private_unity_handler_t *this, identification_t *server, + private_unity_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -378,10 +380,9 @@ METHOD(enumerator_t, enumerate_attributes, bool, } METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, - unity_handler_t *this, identification_t *id, linked_list_t *vips) + unity_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips) { attribute_enumerator_t *enumerator; - ike_sa_t *ike_sa; ike_sa = charon->bus->get_sa(charon->bus); if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 || @@ -402,7 +403,7 @@ typedef struct { /** mutex to unlock */ mutex_t *mutex; /** IKE_SA ID to filter for */ - u_int32_t id; + ike_sa_id_t *id; } include_filter_t; /** @@ -411,7 +412,7 @@ typedef struct { static bool include_filter(include_filter_t *data, entry_t **entry, traffic_selector_t **ts) { - if ((*entry)->sa == data->id) + if (data->id->equals(data->id, (*entry)->id)) { *ts = (*entry)->ts; return TRUE; @@ -429,7 +430,7 @@ static void destroy_filter(include_filter_t *data) } METHOD(unity_handler_t, create_include_enumerator, enumerator_t*, - private_unity_handler_t *this, u_int32_t id) + private_unity_handler_t *this, ike_sa_id_t *id) { include_filter_t *data; diff --git a/src/libcharon/plugins/unity/unity_handler.h b/src/libcharon/plugins/unity/unity_handler.h index 8656fd372..18efe293b 100644 --- a/src/libcharon/plugins/unity/unity_handler.h +++ b/src/libcharon/plugins/unity/unity_handler.h @@ -21,6 +21,7 @@ #ifndef UNITY_HANDLER_H_ #define UNITY_HANDLER_H_ +#include <sa/ike_sa_id.h> #include <attributes/attribute_handler.h> typedef struct unity_handler_t unity_handler_t; @@ -38,11 +39,11 @@ struct unity_handler_t { /** * Create an enumerator over Split-Include attributes received for an IKE_SA. * - * @param id IKE_SA unique ID to get Split-Includes for + * @param id IKE_SA ID to get Split-Includes for * @return enumerator over traffic_selector_t* */ enumerator_t* (*create_include_enumerator)(unity_handler_t *this, - u_int32_t id); + ike_sa_id_t *id); /** * Destroy a unity_handler_t. diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c index 52a2c7f24..227d24be8 100644 --- a/src/libcharon/plugins/unity/unity_narrow.c +++ b/src/libcharon/plugins/unity/unity_narrow.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2014 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG * @@ -16,6 +19,8 @@ #include "unity_narrow.h" #include <daemon.h> +#include <encoding/payloads/id_payload.h> +#include <collections/hashtable.h> typedef struct private_unity_narrow_t private_unity_narrow_t; @@ -33,6 +38,11 @@ struct private_unity_narrow_t { * Unity attribute handler */ unity_handler_t *handler; + + /** + * IKE_SAs for which we received 0.0.0.0/0 as remote traffic selector + */ + hashtable_t *wildcard_ts; }; /** @@ -65,7 +75,7 @@ static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa, enumerator_t *enumerator; enumerator = this->handler->create_include_enumerator(this->handler, - ike_sa->get_unique_id(ike_sa)); + ike_sa->get_id(ike_sa)); while (enumerator->enumerate(enumerator, ¤t)) { if (orig == NULL) @@ -149,7 +159,7 @@ static bool has_split_includes(private_unity_narrow_t *this, ike_sa_t *ike_sa) bool has; enumerator = this->handler->create_include_enumerator(this->handler, - ike_sa->get_unique_id(ike_sa)); + ike_sa->get_id(ike_sa)); has = enumerator->enumerate(enumerator, &ts); enumerator->destroy(enumerator); @@ -191,11 +201,19 @@ METHOD(listener_t, narrow, bool, { case NARROW_INITIATOR_PRE_AUTH: case NARROW_RESPONDER: - narrow_pre(local, "us"); + if (this->wildcard_ts->get(this->wildcard_ts, ike_sa)) + { + narrow_pre(local, "us"); + + } break; case NARROW_INITIATOR_POST_AUTH: case NARROW_RESPONDER_POST: - narrow_responder_post(child_sa->get_config(child_sa), local); + if (this->wildcard_ts->get(this->wildcard_ts, ike_sa)) + { + narrow_responder_post(child_sa->get_config(child_sa), + local); + } break; default: break; @@ -205,9 +223,69 @@ METHOD(listener_t, narrow, bool, return TRUE; } +METHOD(listener_t, message, bool, + private_unity_narrow_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming, bool plain) +{ + traffic_selector_t *tsr = NULL, *wildcard; + enumerator_t *enumerator; + id_payload_t *id_payload; + payload_t *payload; + bool first = TRUE; + + if (!incoming || !plain || + message->get_exchange_type(message) != QUICK_MODE || + !ike_sa || !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY)) + { + return TRUE; + } + enumerator = message->create_payload_enumerator(message); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == PLV1_ID) + { + if (!first) + { + id_payload = (id_payload_t*)payload; + tsr = id_payload->get_ts(id_payload); + break; + } + first = FALSE; + } + } + enumerator->destroy(enumerator); + if (!tsr) + { + return TRUE; + } + wildcard = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535); + if (tsr->equals(tsr, wildcard)) + { + this->wildcard_ts->put(this->wildcard_ts, ike_sa, ike_sa); + } + else + { + this->wildcard_ts->remove(this->wildcard_ts, ike_sa); + } + wildcard->destroy(wildcard); + tsr->destroy(tsr); + return TRUE; +} + +METHOD(listener_t, ike_updown, bool, + private_unity_narrow_t *this, ike_sa_t *ike_sa, bool up) +{ + if (!up) + { + this->wildcard_ts->remove(this->wildcard_ts, ike_sa); + } + return TRUE; +} + METHOD(unity_narrow_t, destroy, void, private_unity_narrow_t *this) { + this->wildcard_ts->destroy(this->wildcard_ts); free(this); } @@ -222,10 +300,14 @@ unity_narrow_t *unity_narrow_create(unity_handler_t *handler) .public = { .listener = { .narrow = _narrow, + .message = _message, + .ike_updown = _ike_updown, }, .destroy = _destroy, }, .handler = handler, + .wildcard_ts = hashtable_create(hashtable_hash_ptr, + hashtable_equals_ptr, 4), ); return &this->public; diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c index 9e4571d34..b7a3fee2e 100644 --- a/src/libcharon/plugins/unity/unity_plugin.c +++ b/src/libcharon/plugins/unity/unity_plugin.c @@ -19,7 +19,6 @@ #include "unity_provider.h" #include <daemon.h> -#include <hydra.h> typedef struct private_unity_plugin_t private_unity_plugin_t; @@ -63,19 +62,19 @@ static bool plugin_cb(private_unity_plugin_t *this, { if (reg) { - hydra->attributes->add_handler(hydra->attributes, - &this->handler->handler); - hydra->attributes->add_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); + charon->attributes->add_provider(charon->attributes, + &this->provider->provider); charon->bus->add_listener(charon->bus, &this->narrower->listener); } else { charon->bus->remove_listener(charon->bus, &this->narrower->listener); - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); - hydra->attributes->remove_provider(hydra->attributes, - &this->provider->provider); + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); + charon->attributes->remove_provider(charon->attributes, + &this->provider->provider); } return TRUE; diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c index 86f81fcfb..1e297a39e 100644 --- a/src/libcharon/plugins/unity/unity_provider.c +++ b/src/libcharon/plugins/unity/unity_provider.c @@ -135,19 +135,17 @@ static bool use_ts(traffic_selector_t *ts) } METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, - private_unity_provider_t *this, linked_list_t *pools, identification_t *id, + private_unity_provider_t *this, linked_list_t *pools, ike_sa_t *ike_sa, linked_list_t *vips) { attribute_enumerator_t *attr_enum; enumerator_t *enumerator; linked_list_t *list, *current; traffic_selector_t *ts; - ike_sa_t *ike_sa; peer_cfg_t *peer_cfg; child_cfg_t *child_cfg; - ike_sa = charon->bus->get_sa(charon->bus); - if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 || + if (ike_sa->get_version(ike_sa) != IKEV1 || !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY) || !vips->get_count(vips)) { diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in index 834d373f3..619d17a0e 100644 --- a/src/libcharon/plugins/updown/Makefile.in +++ b/src/libcharon/plugins/updown/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/updown/updown_handler.c b/src/libcharon/plugins/updown/updown_handler.c index 0894d2d07..72d7f7da3 100644 --- a/src/libcharon/plugins/updown/updown_handler.c +++ b/src/libcharon/plugins/updown/updown_handler.c @@ -62,19 +62,13 @@ static void attributes_destroy(attributes_t *this) } METHOD(attribute_handler_t, handle, bool, - private_updown_handler_t *this, identification_t *server, + private_updown_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { attributes_t *current, *attr = NULL; enumerator_t *enumerator; - ike_sa_t *ike_sa; host_t *host; - ike_sa = charon->bus->get_sa(charon->bus); - if (!ike_sa) - { - return FALSE; - } switch (type) { case INTERNAL_IP4_DNS: @@ -117,12 +111,11 @@ METHOD(attribute_handler_t, handle, bool, } METHOD(attribute_handler_t, release, void, - private_updown_handler_t *this, identification_t *server, + private_updown_handler_t *this, ike_sa_t *ike_sa, configuration_attribute_type_t type, chunk_t data) { attributes_t *attr; enumerator_t *enumerator, *servers; - ike_sa_t *ike_sa; host_t *host; bool found = FALSE; int family; @@ -139,43 +132,39 @@ METHOD(attribute_handler_t, release, void, return; } - ike_sa = charon->bus->get_sa(charon->bus); - if (ike_sa) + this->lock->write_lock(this->lock); + enumerator = this->attrs->create_enumerator(this->attrs); + while (enumerator->enumerate(enumerator, &attr)) { - this->lock->write_lock(this->lock); - enumerator = this->attrs->create_enumerator(this->attrs); - while (enumerator->enumerate(enumerator, &attr)) + if (attr->id == ike_sa->get_unique_id(ike_sa)) { - if (attr->id == ike_sa->get_unique_id(ike_sa)) + servers = attr->dns->create_enumerator(attr->dns); + while (servers->enumerate(servers, &host)) { - servers = attr->dns->create_enumerator(attr->dns); - while (servers->enumerate(servers, &host)) + if (host->get_family(host) == family && + chunk_equals(data, host->get_address(host))) { - if (host->get_family(host) == family && - chunk_equals(data, host->get_address(host))) - { - attr->dns->remove_at(attr->dns, servers); - host->destroy(host); - found = TRUE; - break; - } - } - servers->destroy(servers); - if (attr->dns->get_count(attr->dns) == 0) - { - this->attrs->remove_at(this->attrs, enumerator); - attributes_destroy(attr); + attr->dns->remove_at(attr->dns, servers); + host->destroy(host); + found = TRUE; break; } } - if (found) + servers->destroy(servers); + if (attr->dns->get_count(attr->dns) == 0) { + this->attrs->remove_at(this->attrs, enumerator); + attributes_destroy(attr); break; } } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); + if (found) + { + break; + } } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } METHOD(updown_handler_t, create_dns_enumerator, enumerator_t*, diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c index 1d15cc55e..be65d599f 100644 --- a/src/libcharon/plugins/updown/updown_listener.c +++ b/src/libcharon/plugins/updown/updown_listener.c @@ -243,6 +243,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa, me = ike_sa->get_my_host(ike_sa); other = ike_sa->get_other_host(ike_sa); + push_env(envp, countof(envp), "PATH=%s", getenv("PATH")); push_env(envp, countof(envp), "PLUTO_VERSION=1.1"); is_host = my_ts->is_host(my_ts, me); if (is_host) diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c index d30267dee..60ecfcce6 100644 --- a/src/libcharon/plugins/updown/updown_plugin.c +++ b/src/libcharon/plugins/updown/updown_plugin.c @@ -18,7 +18,6 @@ #include "updown_handler.h" #include <daemon.h> -#include <hydra.h> typedef struct private_updown_plugin_t private_updown_plugin_t; @@ -61,8 +60,8 @@ static bool plugin_cb(private_updown_plugin_t *this, "%s.plugins.updown.dns_handler", FALSE, lib->ns)) { this->handler = updown_handler_create(); - hydra->attributes->add_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->add_handler(charon->attributes, + &this->handler->handler); } this->listener = updown_listener_create(this->handler); charon->bus->add_listener(charon->bus, &this->listener->listener); @@ -74,8 +73,8 @@ static bool plugin_cb(private_updown_plugin_t *this, if (this->handler) { this->handler->destroy(this->handler); - hydra->attributes->remove_handler(hydra->attributes, - &this->handler->handler); + charon->attributes->remove_handler(charon->attributes, + &this->handler->handler); } } return TRUE; diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am index da71de394..b25396085 100644 --- a/src/libcharon/plugins/vici/Makefile.am +++ b/src/libcharon/plugins/vici/Makefile.am @@ -74,3 +74,7 @@ SUBDIRS = if USE_RUBY_GEMS SUBDIRS += ruby endif + +if USE_PYTHON_EGGS +SUBDIRS += python +endif diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in index 34546b905..b63226daa 100644 --- a/src/libcharon/plugins/vici/Makefile.in +++ b/src/libcharon/plugins/vici/Makefile.in @@ -81,6 +81,7 @@ host_triplet = @host@ TESTS = vici_tests$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) @USE_RUBY_GEMS_TRUE@am__append_1 = ruby +@USE_PYTHON_EGGS_TRUE@am__append_2 = python subdir = src/libcharon/plugins/vici DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -269,7 +270,7 @@ am__tty_colors = { \ std='[m'; \ fi; \ } -DIST_SUBDIRS = ruby +DIST_SUBDIRS = ruby python DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -321,6 +322,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -381,10 +383,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -458,6 +462,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ @@ -571,7 +577,7 @@ vici_tests_LDADD = \ $(top_builddir)/src/libstrongswan/libstrongswan.la \ $(top_builddir)/src/libstrongswan/tests/libtest.la -SUBDIRS = $(am__append_1) +SUBDIRS = $(am__append_1) $(am__append_2) all: all-recursive .SUFFIXES: diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md index 272491052..0ce4271b0 100644 --- a/src/libcharon/plugins/vici/README.md +++ b/src/libcharon/plugins/vici/README.md @@ -145,25 +145,25 @@ the following C array: char msg[] = { /* key1 = value1 */ - 2, 4,'k','e','y','1', 0,6,'v','a','l','u','e','1', + 3, 4,'k','e','y','1', 0,6,'v','a','l','u','e','1', /* section1 */ - 0, 8,'s','e','c','t','i','o','n','1', + 1, 8,'s','e','c','t','i','o','n','1', /* sub-section */ - 0, 11,'s','u','b','-','s','e','c','t','i','o','n', + 1, 11,'s','u','b','-','s','e','c','t','i','o','n', /* key2 = value2 */ - 2, 4,'k','e','y','2', 0,6,'v','a','l','u','e','2', + 3, 4,'k','e','y','2', 0,6,'v','a','l','u','e','2', /* sub-section end */ - 1, + 2, /* list1 */ - 3, 5, 'l','i','s','t','1', + 4, 5, 'l','i','s','t','1', /* item1 */ - 4, 0,5,'i','t','e','m','1', + 5, 0,5,'i','t','e','m','1', /* item2 */ - 4, 0,5,'i','t','e','m','2', + 5, 0,5,'i','t','e','m','2', /* list1 end */ - 5, + 6, /* section1 end */ - 1, + 2, }; ## Client-initiated commands ## @@ -559,6 +559,7 @@ command. ] child-sas = { <child-sa-name>* = { + uniqueid = <unique CHILD_SA identifier> reqid = <reqid of CHILD_SA> state = <state string of CHILD_SA> mode = <IPsec mode, tunnel|transport|beet> @@ -820,9 +821,9 @@ during encoding. ## Connecting to the daemon ## -To create a connection to the daemon, a socket must be passed to the -_Connection_ constructor. There is no default, but on Unix systems usually -a Unix socket over _/var/run/charon.vici_ is used: +To create a connection to the daemon, a socket can be passed to the +_Connection_ constructor. If none is passed, a default Unix socket at +_/var/run/charon.vici_ is used: require "vici" require "socket" @@ -854,3 +855,73 @@ _list-conns_ command and implicitly the _list-conn_ event: For more details about the ruby gem refer to the comments in the gem source code or the generated documentation. + +# vici Python egg # + +The _vici Python egg_ is a pure Python implementation of the VICI protocol to +implement client applications. It is provided in the _python_ subdirectory, and +gets built and installed if strongSwan has been _./configure_'d with +_--enable-vici_ and _--enable-python-eggs_. + +The _vici_ module provides a _Session()_ constructor for a high level interface, +the underlying classes are usually not required to build Python applications +using VICI. The _Session_ class provides methods for the supported VICI +commands. + +To represent the VICI message data tree, the library converts the binary +encoding to Python data types. The _Session_ class takes and returns Python +objects for the exchanged message data: + * Sections get encoded as OrderedDict, containing other sections, or + * Key/Values, where the values are strings as dictionary values + * Lists get encoded as Python Lists with string values +Values that do not conform to Python dict or list get converted to strings using +str(). + +## Connecting to the daemon ## + +To create a connection to the daemon, a socket can be passed to the _Session_ +constructor. If none is passed, a default Unix socket at _/var/run/charon.vici_ +is used: + + import vici + import socket + + s = socket.socket(socket.AF_UNIX) + s.connect("/var/run/charon.vici") + v = vici.Session(s) + +## A simple client request ## + +An example to print the daemon version information is as simple as: + + ver = v.version() + + print "{daemon} {version} ({sysname}, {release}, {machine})".format(**ver) + +## A request with response iteration ## + +The _Session_ class returns an iterable Python generator for streamed events to +continuously stream objects to the caller. The following example lists all +loaded connections using the _list-conns_ command and implicitly the _list-conn_ +event: + + for conn in v.list_conns(): + for key in conn: + print key + +Please note that if the returned generator is not iterated completely, it must +be closed using _close()_. This is implicitly done when breaking from a loop, +but an explicit call may be required when directly iterating the generator with +_next()_. + +## Sorting in dictionaries ## + +In VICI, in some message trees the order of objects in dictionary matters. In +contrast to ruby Hashes, Python dictionaries do not preserve order of added +objects. It is therefore recommended to use OrderedDicts instead of the default +dictionaries. Objects returned by the library use OrderedDicts. + +## API documentation ## + +For more details about the Python egg refer to the comments in the Python source +code. diff --git a/src/libcharon/plugins/vici/libvici.c b/src/libcharon/plugins/vici/libvici.c index c0205ccb6..7c98c8b69 100644 --- a/src/libcharon/plugins/vici/libvici.c +++ b/src/libcharon/plugins/vici/libvici.c @@ -427,14 +427,8 @@ vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn) void vici_free_req(vici_req_t *req) { - vici_message_t *message; - free(req->name); - message = req->b->finalize(req->b); - if (message) - { - message->destroy(message); - } + req->b->destroy(req->b); free(req); } diff --git a/src/libcharon/plugins/vici/python/LICENSE b/src/libcharon/plugins/vici/python/LICENSE new file mode 100644 index 000000000..111523ca8 --- /dev/null +++ b/src/libcharon/plugins/vici/python/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Björn Schuberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/libcharon/plugins/vici/python/MANIFEST.in b/src/libcharon/plugins/vici/python/MANIFEST.in new file mode 100644 index 000000000..1aba38f67 --- /dev/null +++ b/src/libcharon/plugins/vici/python/MANIFEST.in @@ -0,0 +1 @@ +include LICENSE diff --git a/src/libcharon/plugins/vici/python/Makefile.am b/src/libcharon/plugins/vici/python/Makefile.am new file mode 100644 index 000000000..f51737870 --- /dev/null +++ b/src/libcharon/plugins/vici/python/Makefile.am @@ -0,0 +1,33 @@ +EXTRA_DIST = LICENSE MANIFEST.in \ + setup.py.in \ + vici/test/__init__.py \ + vici/test/test_protocol.py \ + vici/__init__.py \ + vici/compat.py \ + vici/exception.py \ + vici/protocol.py \ + vici/session.py + +setup.py: $(srcdir)/setup.py.in + $(AM_V_GEN) sed \ + -e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \ + $(srcdir)/setup.py.in > $@ + +all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + +dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py + (cd $(srcdir); $(PYTHON) setup.py bdist_egg \ + -b $(shell readlink -f $(builddir))/build \ + -d $(shell readlink -f $(builddir))/dist) + +clean-local: setup.py + $(PYTHON) setup.py clean -a + rm -rf vici.egg-info dist setup.py + +install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + $(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \ + dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + +if USE_PY_TEST + TESTS = $(PY_TEST) +endif diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in new file mode 100644 index 000000000..3a5e5ea72 --- /dev/null +++ b/src/libcharon/plugins/vici/python/Makefile.in @@ -0,0 +1,686 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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/vici/python +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +EXTRA_DIST = LICENSE MANIFEST.in \ + setup.py.in \ + vici/test/__init__.py \ + vici/test/test_protocol.py \ + vici/__init__.py \ + vici/compat.py \ + vici/exception.py \ + vici/protocol.py \ + vici/session.py + +@USE_PY_TEST_TRUE@TESTS = $(PY_TEST) +all: all-am + +.SUFFIXES: +$(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/vici/python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/plugins/vici/python/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +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 + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile all-local +installdirs: +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-exec-local + +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 -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: all all-am all-local check check-TESTS check-am clean \ + clean-generic clean-libtool clean-local cscopelist-am ctags-am \ + distclean distclean-generic distclean-libtool 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-exec-local install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + + +setup.py: $(srcdir)/setup.py.in + $(AM_V_GEN) sed \ + -e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \ + $(srcdir)/setup.py.in > $@ + +all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + +dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py + (cd $(srcdir); $(PYTHON) setup.py bdist_egg \ + -b $(shell readlink -f $(builddir))/build \ + -d $(shell readlink -f $(builddir))/dist) + +clean-local: setup.py + $(PYTHON) setup.py clean -a + rm -rf vici.egg-info dist setup.py + +install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + $(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \ + dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg + +# 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/vici/python/setup.py.in b/src/libcharon/plugins/vici/python/setup.py.in new file mode 100644 index 000000000..0e4ad8236 --- /dev/null +++ b/src/libcharon/plugins/vici/python/setup.py.in @@ -0,0 +1,34 @@ +from setuptools import setup + + +long_description = ( + "The strongSwan VICI protocol allows external application to monitor, " + "configure and control the IKE daemon charon. This python package provides " + "a native client side implementation of the VICI protocol, well suited to " + "script automated tasks in a reliable way." +) + +setup( + name="vici", + version="@EGG_VERSION@", + description="Native python interface for strongSwan VICI", + author="Bjorn Schuberg", + url="https://wiki.strongswan.org/projects/strongswan/wiki/Vici", + license="MIT", + packages=["vici"], + long_description=long_description, + include_package_data=True, + classifiers=( + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.2", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Topic :: Security", + "Topic :: Software Development :: Libraries", + ) +) diff --git a/src/libcharon/plugins/vici/python/vici/__init__.py b/src/libcharon/plugins/vici/python/vici/__init__.py new file mode 100644 index 000000000..d314325b6 --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/__init__.py @@ -0,0 +1 @@ +from .session import Session diff --git a/src/libcharon/plugins/vici/python/vici/compat.py b/src/libcharon/plugins/vici/python/vici/compat.py new file mode 100644 index 000000000..b5f46992e --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/compat.py @@ -0,0 +1,14 @@ +# Help functions for compatibility between python version 2 and 3 + + +# From http://legacy.python.org/dev/peps/pep-0469 +try: + dict.iteritems +except AttributeError: + # python 3 + def iteritems(d): + return iter(d.items()) +else: + # python 2 + def iteritems(d): + return d.iteritems() diff --git a/src/libcharon/plugins/vici/python/vici/exception.py b/src/libcharon/plugins/vici/python/vici/exception.py new file mode 100644 index 000000000..36384e556 --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/exception.py @@ -0,0 +1,10 @@ +"""Exception types that may be thrown by this library.""" + +class DeserializationException(Exception): + """Encountered an unexpected byte sequence or missing element type.""" + +class SessionException(Exception): + """Session request exception.""" + +class CommandException(Exception): + """Command result exception.""" diff --git a/src/libcharon/plugins/vici/python/vici/protocol.py b/src/libcharon/plugins/vici/python/vici/protocol.py new file mode 100644 index 000000000..855a7b2e2 --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/protocol.py @@ -0,0 +1,196 @@ +import io +import socket +import struct + +from collections import namedtuple +from collections import OrderedDict + +from .compat import iteritems +from .exception import DeserializationException + + +class Transport(object): + HEADER_LENGTH = 4 + MAX_SEGMENT = 512 * 1024 + + def __init__(self, sock): + self.socket = sock + + def send(self, packet): + self.socket.sendall(struct.pack("!I", len(packet)) + packet) + + def receive(self): + raw_length = self.socket.recv(self.HEADER_LENGTH) + length, = struct.unpack("!I", raw_length) + payload = self.socket.recv(length) + return payload + + def close(self): + self.socket.shutdown(socket.SHUT_RDWR) + self.socket.close() + + +class Packet(object): + CMD_REQUEST = 0 # Named request message + CMD_RESPONSE = 1 # Unnamed response message for a request + CMD_UNKNOWN = 2 # Unnamed response if requested command is unknown + EVENT_REGISTER = 3 # Named event registration request + EVENT_UNREGISTER = 4 # Named event de-registration request + EVENT_CONFIRM = 5 # Unnamed confirmation for event (de-)registration + EVENT_UNKNOWN = 6 # Unnamed response if event (de-)registration failed + EVENT = 7 # Named event message + + ParsedPacket = namedtuple( + "ParsedPacket", + ["response_type", "payload"] + ) + + ParsedEventPacket = namedtuple( + "ParsedEventPacket", + ["response_type", "event_type", "payload"] + ) + + @classmethod + def _named_request(cls, request_type, request, message=None): + request = request.encode() + payload = struct.pack("!BB", request_type, len(request)) + request + if message is not None: + return payload + message + else: + return payload + + @classmethod + def request(cls, command, message=None): + return cls._named_request(cls.CMD_REQUEST, command, message) + + @classmethod + def register_event(cls, event_type): + return cls._named_request(cls.EVENT_REGISTER, event_type) + + @classmethod + def unregister_event(cls, event_type): + return cls._named_request(cls.EVENT_UNREGISTER, event_type) + + @classmethod + def parse(cls, packet): + stream = FiniteStream(packet) + response_type, = struct.unpack("!B", stream.read(1)) + + if response_type == cls.EVENT: + length, = struct.unpack("!B", stream.read(1)) + event_type = stream.read(length) + return cls.ParsedEventPacket(response_type, event_type, stream) + else: + return cls.ParsedPacket(response_type, stream) + + +class Message(object): + SECTION_START = 1 # Begin a new section having a name + SECTION_END = 2 # End a previously started section + KEY_VALUE = 3 # Define a value for a named key in the section + LIST_START = 4 # Begin a named list for list items + LIST_ITEM = 5 # Define an unnamed item value in the current list + LIST_END = 6 # End a previously started list + + @classmethod + def serialize(cls, message): + def encode_named_type(marker, name): + name = name.encode() + return struct.pack("!BB", marker, len(name)) + name + + def encode_blob(value): + if not isinstance(value, bytes): + value = str(value).encode() + return struct.pack("!H", len(value)) + value + + def serialize_list(lst): + segment = bytes() + for item in lst: + segment += struct.pack("!B", cls.LIST_ITEM) + encode_blob(item) + return segment + + def serialize_dict(d): + segment = bytes() + for key, value in iteritems(d): + if isinstance(value, dict): + segment += ( + encode_named_type(cls.SECTION_START, key) + + serialize_dict(value) + + struct.pack("!B", cls.SECTION_END) + ) + elif isinstance(value, list): + segment += ( + encode_named_type(cls.LIST_START, key) + + serialize_list(value) + + struct.pack("!B", cls.LIST_END) + ) + else: + segment += ( + encode_named_type(cls.KEY_VALUE, key) + + encode_blob(value) + ) + return segment + + return serialize_dict(message) + + @classmethod + def deserialize(cls, stream): + def decode_named_type(stream): + length, = struct.unpack("!B", stream.read(1)) + return stream.read(length).decode() + + def decode_blob(stream): + length, = struct.unpack("!H", stream.read(2)) + return stream.read(length) + + def decode_list_item(stream): + marker, = struct.unpack("!B", stream.read(1)) + while marker == cls.LIST_ITEM: + yield decode_blob(stream) + marker, = struct.unpack("!B", stream.read(1)) + + if marker != cls.LIST_END: + raise DeserializationException( + "Expected end of list at {pos}".format(pos=stream.tell()) + ) + + section = OrderedDict() + section_stack = [] + while stream.has_more(): + element_type, = struct.unpack("!B", stream.read(1)) + if element_type == cls.SECTION_START: + section_name = decode_named_type(stream) + new_section = OrderedDict() + section[section_name] = new_section + section_stack.append(section) + section = new_section + + elif element_type == cls.LIST_START: + list_name = decode_named_type(stream) + section[list_name] = [item for item in decode_list_item(stream)] + + elif element_type == cls.KEY_VALUE: + key = decode_named_type(stream) + section[key] = decode_blob(stream) + + elif element_type == cls.SECTION_END: + if len(section_stack): + section = section_stack.pop() + else: + raise DeserializationException( + "Unexpected end of section at {pos}".format( + pos=stream.tell() + ) + ) + + if len(section_stack): + raise DeserializationException("Expected end of section") + return section + + +class FiniteStream(io.BytesIO): + def __len__(self): + return len(self.getvalue()) + + def has_more(self): + return self.tell() < len(self) diff --git a/src/libcharon/plugins/vici/python/vici/session.py b/src/libcharon/plugins/vici/python/vici/session.py new file mode 100644 index 000000000..dee58699d --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/session.py @@ -0,0 +1,327 @@ +import collections +import socket + +from .exception import SessionException, CommandException +from .protocol import Transport, Packet, Message + + +class Session(object): + def __init__(self, sock=None): + if sock is None: + sock = socket.socket(socket.AF_UNIX) + sock.connect("/var/run/charon.vici") + self.handler = SessionHandler(Transport(sock)) + + def version(self): + """Retrieve daemon and system specific version information. + + :return: daemon and system specific version information + :rtype: dict + """ + return self.handler.request("version") + + def stats(self): + """Retrieve IKE daemon statistics and load information. + + :return: IKE daemon statistics and load information + :rtype: dict + """ + return self.handler.request("stats") + + def reload_settings(self): + """Reload strongswan.conf settings and any plugins supporting reload. + """ + self.handler.request("reload-settings") + + def initiate(self, sa): + """Initiate an SA. + + :param sa: the SA to initiate + :type sa: dict + :return: generator for logs emitted as dict + :rtype: generator + """ + return self.handler.streamed_request("initiate", "control-log", sa) + + def terminate(self, sa): + """Terminate an SA. + + :param sa: the SA to terminate + :type sa: dict + :return: generator for logs emitted as dict + :rtype: generator + """ + return self.handler.streamed_request("terminate", "control-log", sa) + + def install(self, policy): + """Install a trap, drop or bypass policy defined by a CHILD_SA config. + + :param policy: policy to install + :type policy: dict + """ + self.handler.request("install", policy) + + def uninstall(self, policy): + """Uninstall a trap, drop or bypass policy defined by a CHILD_SA config. + + :param policy: policy to uninstall + :type policy: dict + """ + self.handler.request("uninstall", policy) + + def list_sas(self, filters=None): + """Retrieve active IKE_SAs and associated CHILD_SAs. + + :param filters: retrieve only matching IKE_SAs (optional) + :type filters: dict + :return: generator for active IKE_SAs and associated CHILD_SAs as dict + :rtype: generator + """ + return self.handler.streamed_request("list-sas", "list-sa", filters) + + def list_policies(self, filters=None): + """Retrieve installed trap, drop and bypass policies. + + :param filters: retrieve only matching policies (optional) + :type filters: dict + :return: generator for installed trap, drop and bypass policies as dict + :rtype: generator + """ + return self.handler.streamed_request("list-policies", "list-policy", + filters) + + def list_conns(self, filters=None): + """Retrieve loaded connections. + + :param filters: retrieve only matching configuration names (optional) + :type filters: dict + :return: generator for loaded connections as dict + :rtype: generator + """ + return self.handler.streamed_request("list-conns", "list-conn", + filters) + + def get_conns(self): + """Retrieve connection names loaded exclusively over vici. + + :return: connection names + :rtype: dict + """ + return self.handler.request("get-conns") + + def list_certs(self, filters=None): + """Retrieve loaded certificates. + + :param filters: retrieve only matching certificates (optional) + :type filters: dict + :return: generator for loaded certificates as dict + :rtype: generator + """ + return self.handler.streamed_request("list-certs", "list-cert", filters) + + def load_conn(self, connection): + """Load a connection definition into the daemon. + + :param connection: connection definition + :type connection: dict + """ + self.handler.request("load-conn", connection) + + def unload_conn(self, name): + """Unload a connection definition. + + :param name: connection definition name + :type name: dict + """ + self.handler.request("unload-conn", name) + + def load_cert(self, certificate): + """Load a certificate into the daemon. + + :param certificate: PEM or DER encoded certificate + :type certificate: dict + """ + self.handler.request("load-cert", certificate) + + def load_key(self, private_key): + """Load a private key into the daemon. + + :param private_key: PEM or DER encoded key + """ + self.handler.request("load-key", private_key) + + def load_shared(self, secret): + """Load a shared IKE PSK, EAP or XAuth secret into the daemon. + + :param secret: shared IKE PSK, EAP or XAuth secret + :type secret: dict + """ + self.handler.request("load-shared", secret) + + def clear_creds(self): + """Clear credentials loaded over vici. + + Clear all loaded certificate, private key and shared key credentials. + This affects only credentials loaded over vici, but additionally + flushes the credential cache. + """ + self.handler.request("clear-creds") + + def load_pool(self, pool): + """Load a virtual IP pool. + + Load an in-memory virtual IP and configuration attribute pool. + Existing pools with the same name get updated, if possible. + + :param pool: virtual IP and configuration attribute pool + :type pool: dict + """ + return self.handler.request("load-pool", pool) + + def unload_pool(self, pool_name): + """Unload a virtual IP pool. + + Unload a previously loaded virtual IP and configuration attribute pool. + Unloading fails for pools with leases currently online. + + :param pool_name: pool by name + :type pool_name: dict + """ + self.handler.request("unload-pool", pool_name) + + def get_pools(self): + """Retrieve loaded pools. + + :return: loaded pools + :rtype: dict + """ + return self.handler.request("get-pools") + + +class SessionHandler(object): + """Handles client command execution requests over vici.""" + + def __init__(self, transport): + self.transport = transport + + def _communicate(self, packet): + """Send packet over transport and parse response. + + :param packet: packet to send + :type packet: :py:class:`vici.protocol.Packet` + :return: parsed packet in a tuple with message type and payload + :rtype: :py:class:`collections.namedtuple` + """ + self.transport.send(packet) + return Packet.parse(self.transport.receive()) + + def request(self, command, message=None): + """Send request with an optional message. + + :param command: command to send + :type command: str + :param message: message (optional) + :type message: str + :return: command result + :rtype: dict + """ + if message is not None: + message = Message.serialize(message) + packet = Packet.request(command, message) + response = self._communicate(packet) + + if response.response_type != Packet.CMD_RESPONSE: + raise SessionException( + "Unexpected response type {type}, " + "expected '{response}' (CMD_RESPONSE)".format( + type=response.response_type, + response=Packet.CMD_RESPONSE + ) + ) + + command_response = Message.deserialize(response.payload) + if "success" in command_response: + if command_response["success"] != b"yes": + raise CommandException( + "Command failed: {errmsg}".format( + errmsg=command_response["errmsg"] + ) + ) + + return command_response + + def streamed_request(self, command, event_stream_type, message=None): + """Send command request and collect and return all emitted events. + + :param command: command to send + :type command: str + :param event_stream_type: event type emitted on command execution + :type event_stream_type: str + :param message: message (optional) + :type message: str + :return: generator for streamed event responses as dict + :rtype: generator + """ + if message is not None: + message = Message.serialize(message) + + # subscribe to event stream + packet = Packet.register_event(event_stream_type) + response = self._communicate(packet) + + if response.response_type != Packet.EVENT_CONFIRM: + raise SessionException( + "Unexpected response type {type}, " + "expected '{confirm}' (EVENT_CONFIRM)".format( + type=response.response_type, + confirm=Packet.EVENT_CONFIRM, + ) + ) + + # issue command, and read any event messages + packet = Packet.request(command, message) + self.transport.send(packet) + exited = False + while True: + response = Packet.parse(self.transport.receive()) + if response.response_type == Packet.EVENT: + if not exited: + try: + yield Message.deserialize(response.payload) + except GeneratorExit: + exited = True + pass + else: + break + + if response.response_type == Packet.CMD_RESPONSE: + command_response = Message.deserialize(response.payload) + else: + raise SessionException( + "Unexpected response type {type}, " + "expected '{response}' (CMD_RESPONSE)".format( + type=response.response_type, + response=Packet.CMD_RESPONSE + ) + ) + + # unsubscribe from event stream + packet = Packet.unregister_event(event_stream_type) + response = self._communicate(packet) + if response.response_type != Packet.EVENT_CONFIRM: + raise SessionException( + "Unexpected response type {type}, " + "expected '{confirm}' (EVENT_CONFIRM)".format( + type=response.response_type, + confirm=Packet.EVENT_CONFIRM, + ) + ) + + # evaluate command result, if any + if "success" in command_response: + if command_response["success"] != b"yes": + raise CommandException( + "Command failed: {errmsg}".format( + errmsg=command_response["errmsg"] + ) + ) diff --git a/src/libcharon/plugins/vici/python/vici/test/__init__.py b/src/libcharon/plugins/vici/python/vici/test/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/test/__init__.py diff --git a/src/libcharon/plugins/vici/python/vici/test/test_protocol.py b/src/libcharon/plugins/vici/python/vici/test/test_protocol.py new file mode 100644 index 000000000..a1f202d79 --- /dev/null +++ b/src/libcharon/plugins/vici/python/vici/test/test_protocol.py @@ -0,0 +1,144 @@ +import pytest + +from ..protocol import Packet, Message, FiniteStream +from ..exception import DeserializationException + + +class TestPacket(object): + # test data definitions for outgoing packet types + cmd_request = b"\x00\x0c" b"command_type" + cmd_request_msg = b"\x00\x07" b"command" b"payload" + event_register = b"\x03\x0a" b"event_type" + event_unregister = b"\x04\x0a" b"event_type" + + # test data definitions for incoming packet types + cmd_response = b"\x01" b"reply" + cmd_unknown = b"\x02" + event_confirm = b"\x05" + event_unknown = b"\x06" + event = b"\x07\x03" b"log" b"message" + + def test_request(self): + assert Packet.request("command_type") == self.cmd_request + assert Packet.request("command", b"payload") == self.cmd_request_msg + + def test_register_event(self): + assert Packet.register_event("event_type") == self.event_register + + def test_unregister_event(self): + assert Packet.unregister_event("event_type") == self.event_unregister + + def test_parse(self): + parsed_cmd_response = Packet.parse(self.cmd_response) + assert parsed_cmd_response.response_type == Packet.CMD_RESPONSE + assert parsed_cmd_response.payload.getvalue() == self.cmd_response + + parsed_cmd_unknown = Packet.parse(self.cmd_unknown) + assert parsed_cmd_unknown.response_type == Packet.CMD_UNKNOWN + assert parsed_cmd_unknown.payload.getvalue() == self.cmd_unknown + + parsed_event_confirm = Packet.parse(self.event_confirm) + assert parsed_event_confirm.response_type == Packet.EVENT_CONFIRM + assert parsed_event_confirm.payload.getvalue() == self.event_confirm + + parsed_event_unknown = Packet.parse(self.event_unknown) + assert parsed_event_unknown.response_type == Packet.EVENT_UNKNOWN + assert parsed_event_unknown.payload.getvalue() == self.event_unknown + + parsed_event = Packet.parse(self.event) + assert parsed_event.response_type == Packet.EVENT + assert parsed_event.payload.getvalue() == self.event + + +class TestMessage(object): + """Message (de)serialization test.""" + + # data definitions for test of de(serialization) + # serialized messages holding a section + ser_sec_unclosed = b"\x01\x08unclosed" + ser_sec_single = b"\x01\x07section\x02" + ser_sec_nested = b"\x01\x05outer\x01\x0asubsection\x02\x02" + + # serialized messages holding a list + ser_list_invalid = b"\x04\x07invalid\x05\x00\x02e1\x02\x03sec\x06" + ser_list_0_item = b"\x04\x05empty\x06" + ser_list_1_item = b"\x04\x01l\x05\x00\x02e1\x06" + ser_list_2_item = b"\x04\x01l\x05\x00\x02e1\x05\x00\x02e2\x06" + + # serialized messages with key value pairs + ser_kv_pair = b"\x03\x03key\x00\x05value" + ser_kv_zero = b"\x03\x0azerolength\x00\x00" + + # deserialized messages holding a section + des_sec_single = { "section": {} } + des_sec_nested = { "outer": { "subsection": {} } } + + # deserialized messages holding a list + des_list_0_item = { "empty": [] } + des_list_1_item = { "l": [ b"e1" ] } + des_list_2_item = { "l": [ b"e1", b"e2" ] } + + # deserialized messages with key value pairs + des_kv_pair = { "key": b"value" } + des_kv_zero = { "zerolength": b"" } + + def test_section_serialization(self): + assert Message.serialize(self.des_sec_single) == self.ser_sec_single + assert Message.serialize(self.des_sec_nested) == self.ser_sec_nested + + def test_list_serialization(self): + assert Message.serialize(self.des_list_0_item) == self.ser_list_0_item + assert Message.serialize(self.des_list_1_item) == self.ser_list_1_item + assert Message.serialize(self.des_list_2_item) == self.ser_list_2_item + + def test_key_serialization(self): + assert Message.serialize(self.des_kv_pair) == self.ser_kv_pair + assert Message.serialize(self.des_kv_zero) == self.ser_kv_zero + + def test_section_deserialization(self): + single = Message.deserialize(FiniteStream(self.ser_sec_single)) + nested = Message.deserialize(FiniteStream(self.ser_sec_nested)) + + assert single == self.des_sec_single + assert nested == self.des_sec_nested + + with pytest.raises(DeserializationException): + Message.deserialize(FiniteStream(self.ser_sec_unclosed)) + + def test_list_deserialization(self): + l0 = Message.deserialize(FiniteStream(self.ser_list_0_item)) + l1 = Message.deserialize(FiniteStream(self.ser_list_1_item)) + l2 = Message.deserialize(FiniteStream(self.ser_list_2_item)) + + assert l0 == self.des_list_0_item + assert l1 == self.des_list_1_item + assert l2 == self.des_list_2_item + + with pytest.raises(DeserializationException): + Message.deserialize(FiniteStream(self.ser_list_invalid)) + + def test_key_deserialization(self): + pair = Message.deserialize(FiniteStream(self.ser_kv_pair)) + zerolength = Message.deserialize(FiniteStream(self.ser_kv_zero)) + + assert pair == self.des_kv_pair + assert zerolength == self.des_kv_zero + + def test_roundtrip(self): + message = { + "key1": "value1", + "section1": { + "sub-section": { + "key2": b"value2", + }, + "list1": [ "item1", "item2" ], + }, + } + serialized_message = FiniteStream(Message.serialize(message)) + deserialized_message = Message.deserialize(serialized_message) + + # ensure that list items and key values remain as undecoded bytes + deserialized_section = deserialized_message["section1"] + assert deserialized_message["key1"] == b"value1" + assert deserialized_section["sub-section"]["key2"] == b"value2" + assert deserialized_section["list1"] == [ b"item1", b"item2" ] diff --git a/src/libcharon/plugins/vici/ruby/Makefile.am b/src/libcharon/plugins/vici/ruby/Makefile.am index ce38e1c3d..3e12f86cc 100644 --- a/src/libcharon/plugins/vici/ruby/Makefile.am +++ b/src/libcharon/plugins/vici/ruby/Makefile.am @@ -5,8 +5,10 @@ vici.gemspec: $(srcdir)/vici.gemspec.in -e "s:@GEM_VERSION@:$(PACKAGE_VERSION):" \ $(srcdir)/vici.gemspec.in > $@ -vici-$(PACKAGE_VERSION).gem: vici.gemspec - $(GEM) build vici.gemspec +vici-$(PACKAGE_VERSION).gem: vici.gemspec $(EXTRA_DIST) + (cd $(srcdir); $(GEM) build $(abs_builddir)/vici.gemspec) + [ "$(srcdir)" = "$(builddir)" ] || \ + mv $(srcdir)/vici-$(PACKAGE_VERSION).gem $(builddir) all-local: vici-$(PACKAGE_VERSION).gem diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in index c8a8c11fb..f37c09ea2 100644 --- a/src/libcharon/plugins/vici/ruby/Makefile.in +++ b/src/libcharon/plugins/vici/ruby/Makefile.in @@ -142,6 +142,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -202,10 +203,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -279,6 +282,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ @@ -535,8 +540,10 @@ vici.gemspec: $(srcdir)/vici.gemspec.in -e "s:@GEM_VERSION@:$(PACKAGE_VERSION):" \ $(srcdir)/vici.gemspec.in > $@ -vici-$(PACKAGE_VERSION).gem: vici.gemspec - $(GEM) build vici.gemspec +vici-$(PACKAGE_VERSION).gem: vici.gemspec $(EXTRA_DIST) + (cd $(srcdir); $(GEM) build $(abs_builddir)/vici.gemspec) + [ "$(srcdir)" = "$(builddir)" ] || \ + mv $(srcdir)/vici-$(PACKAGE_VERSION).gem $(builddir) all-local: vici-$(PACKAGE_VERSION).gem diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb index e8a9ddca9..f87e46e69 100644 --- a/src/libcharon/plugins/vici/ruby/lib/vici.rb +++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb @@ -243,6 +243,25 @@ module Vici end ## + # Receive data from socket, until len bytes read + def recv_all(len) + encoding = "" + while encoding.length < len do + encoding << @socket.recv(len - encoding.length) + end + encoding + end + + ## + # Send data to socket, until all bytes sent + def send_all(encoding) + len = 0 + while len < encoding.length do + len += @socket.send(encoding[len..-1], 0) + end + end + + ## # Write a packet prefixed by its length over the transport socket. Type # specifies the message, the optional label and message get appended. def write(type, label, message) @@ -253,15 +272,15 @@ module Vici if message encoding << message.encoding end - @socket.send([encoding.length + 1, type].pack("Nc") + encoding, 0) + send_all([encoding.length + 1, type].pack("Nc") + encoding) end ## # Read a packet from the transport socket. Returns the packet type, and # if available in the packet a label and the contained message. def read - len = @socket.recv(4).unpack("N")[0] - encoding = @socket.recv(len) + len = recv_all(4).unpack("N")[0] + encoding = recv_all(len) type = encoding.unpack("c")[0] len = 1 case type @@ -371,7 +390,10 @@ module Vici # during encoding. class Connection - def initialize(socket) + def initialize(socket = nil) + if socket == nil + socket = UNIXSocket.new("/var/run/charon.vici") + end @transp = Transport.new(socket) end diff --git a/src/libcharon/plugins/vici/ruby/vici.gemspec.in b/src/libcharon/plugins/vici/ruby/vici.gemspec.in index 5ad61c0a0..2bd2b3d88 100644 --- a/src/libcharon/plugins/vici/ruby/vici.gemspec.in +++ b/src/libcharon/plugins/vici/ruby/vici.gemspec.in @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = "vici" s.version = "@GEM_VERSION@" s.authors = ["Martin Willi"] - s.email = ["martin@strongswan.ch"] + s.email = ["martin@strongswan.org"] s.description = %q{ The strongSwan VICI protocol allows external application to monitor, configure and control the IKE daemon charon. This ruby gem provides a diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c index 2178116c9..f04bae774 100644 --- a/src/libcharon/plugins/vici/vici_attribute.c +++ b/src/libcharon/plugins/vici/vici_attribute.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2014 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * @@ -93,7 +96,8 @@ static void pool_destroy(pool_t *pool) * Find an existing or not yet existing lease */ static host_t *find_addr(private_vici_attribute_t *this, linked_list_t *pools, - identification_t *id, host_t *requested, mem_pool_op_t op) + identification_t *id, host_t *requested, + mem_pool_op_t op, host_t *peer) { enumerator_t *enumerator; host_t *addr = NULL; @@ -106,7 +110,8 @@ static host_t *find_addr(private_vici_attribute_t *this, linked_list_t *pools, pool = this->pools->get(this->pools, name); if (pool) { - addr = pool->vips->acquire_address(pool->vips, id, requested, op); + addr = pool->vips->acquire_address(pool->vips, id, requested, + op, peer); if (addr) { break; @@ -119,20 +124,24 @@ static host_t *find_addr(private_vici_attribute_t *this, linked_list_t *pools, } METHOD(attribute_provider_t, acquire_address, host_t*, - private_vici_attribute_t *this, linked_list_t *pools, identification_t *id, + private_vici_attribute_t *this, linked_list_t *pools, ike_sa_t *ike_sa, host_t *requested) { - host_t *addr; + identification_t *id; + host_t *addr, *peer; + + id = ike_sa->get_other_eap_id(ike_sa); + peer = ike_sa->get_other_host(ike_sa); this->lock->read_lock(this->lock); - addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING); + addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING, peer); if (!addr) { - addr = find_addr(this, pools, id, requested, MEM_POOL_NEW); + addr = find_addr(this, pools, id, requested, MEM_POOL_NEW, peer); if (!addr) { - addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN); + addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN, peer); } } @@ -143,13 +152,16 @@ METHOD(attribute_provider_t, acquire_address, host_t*, METHOD(attribute_provider_t, release_address, bool, private_vici_attribute_t *this, linked_list_t *pools, host_t *address, - identification_t *id) + ike_sa_t *ike_sa) { enumerator_t *enumerator; + identification_t *id; bool found = FALSE; pool_t *pool; char *name; + id = ike_sa->get_other_eap_id(ike_sa); + this->lock->read_lock(this->lock); enumerator = pools->create_enumerator(pools); @@ -256,7 +268,7 @@ static bool have_vips_from_pool(mem_pool_t *pool, linked_list_t *vips) METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_vici_attribute_t *this, linked_list_t *pools, - identification_t *id, linked_list_t *vips) + ike_sa_t *ike_sa, linked_list_t *vips) { enumerator_t *enumerator; nested_data_t *data; @@ -355,6 +367,24 @@ static vici_message_t* create_reply(char *fmt, ...) } /** + * Parse a range definition of an address pool + */ +static mem_pool_t *create_pool_range(char *name, char *buf) +{ + mem_pool_t *pool; + host_t *from, *to; + + if (!host_create_from_range(buf, &from, &to)) + { + return NULL; + } + pool = mem_pool_create_range(name, from, to); + from->destroy(from); + to->destroy(to); + return pool; +} + +/** * Parse callback data, passed to each callback */ typedef struct { @@ -490,7 +520,8 @@ CALLBACK(pool_kv, bool, if (streq(name, "addrs")) { char buf[128]; - host_t *base; + mem_pool_t *pool; + host_t *base = NULL; int bits; if (data->pool->vips) @@ -503,14 +534,22 @@ CALLBACK(pool_kv, bool, data->request->reply = create_reply("invalid addrs value"); return FALSE; } - base = host_create_from_subnet(buf, &bits); - if (!base) + pool = create_pool_range(data->name, buf); + if (!pool) + { + base = host_create_from_subnet(buf, &bits); + if (base) + { + pool = mem_pool_create(data->name, base, bits); + base->destroy(base); + } + } + if (!pool) { data->request->reply = create_reply("invalid addrs value: %s", buf); return FALSE; } - data->pool->vips = mem_pool_create(data->name, base, bits); - base->destroy(base); + data->pool->vips = pool; return TRUE; } data->request->reply = create_reply("invalid attribute: %s", name); diff --git a/src/libcharon/plugins/vici/vici_builder.c b/src/libcharon/plugins/vici/vici_builder.c index 561632049..82f12c9da 100644 --- a/src/libcharon/plugins/vici/vici_builder.c +++ b/src/libcharon/plugins/vici/vici_builder.c @@ -84,6 +84,8 @@ METHOD(vici_builder_t, add, void, if (value.len > 0xffff) { + DBG1(DBG_ENC, "vici value exceeds size limit (%zu > %u)", + value.len, 0xffff); this->error++; return; } @@ -125,24 +127,58 @@ METHOD(vici_builder_t, add, void, } } -METHOD(vici_builder_t, vadd_kv, void, - private_vici_builder_t *this, char *key, char *fmt, va_list args) +/** + * Add a list item or a key/value, if key given + */ +static void vadd_kv_or_li(private_vici_builder_t *this, char *key, + char *fmt, va_list args) { - char buf[2048]; + u_char buf[512]; + chunk_t value; ssize_t len; + va_list copy; - len = vsnprintf(buf, sizeof(buf), fmt, args); - if (len < 0 || len >= sizeof(buf)) + va_copy(copy, args); + len = vsnprintf(buf, sizeof(buf), fmt, copy); + va_end(copy); + if (len >= sizeof(buf)) { - DBG1(DBG_ENC, "vici builder format buffer exceeds limit"); + value = chunk_alloc(len + 1); + len = vsnprintf(value.ptr, value.len, fmt, args); + } + else + { + value = chunk_create(buf, len); + } + + if (len < 0) + { + DBG1(DBG_ENC, "vici builder format print failed"); this->error++; } else { - add(this, VICI_KEY_VALUE, key, chunk_create(buf, len)); + if (key) + { + add(this, VICI_KEY_VALUE, key, value); + } + else + { + add(this, VICI_LIST_ITEM, value); + } + } + if (value.ptr != buf) + { + free(value.ptr); } } +METHOD(vici_builder_t, vadd_kv, void, + private_vici_builder_t *this, char *key, char *fmt, va_list args) +{ + vadd_kv_or_li(this, key, fmt, args); +} + METHOD(vici_builder_t, add_kv, void, private_vici_builder_t *this, char *key, char *fmt, ...) { @@ -153,23 +189,10 @@ METHOD(vici_builder_t, add_kv, void, va_end(args); } - METHOD(vici_builder_t, vadd_li, void, private_vici_builder_t *this, char *fmt, va_list args) { - char buf[2048]; - ssize_t len; - - len = vsnprintf(buf, sizeof(buf), fmt, args); - if (len < 0 || len >= sizeof(buf)) - { - DBG1(DBG_ENC, "vici builder format buffer exceeds limit"); - this->error++; - } - else - { - add(this, VICI_LIST_ITEM, chunk_create(buf, len)); - } + vadd_kv_or_li(this, NULL, fmt, args); } METHOD(vici_builder_t, add_li, void, @@ -206,6 +229,13 @@ METHOD(vici_builder_t, end_list, void, add(this, VICI_LIST_END); } +METHOD(vici_builder_t, destroy, void, + private_vici_builder_t *this) +{ + this->writer->destroy(this->writer); + free(this); +} + METHOD(vici_builder_t, finalize, vici_message_t*, private_vici_builder_t *this) { @@ -215,14 +245,12 @@ METHOD(vici_builder_t, finalize, vici_message_t*, { DBG1(DBG_ENC, "vici builder error: %u errors (section: %u, list %u)", this->error, this->section, this->list); - this->writer->destroy(this->writer); - free(this); + destroy(this); return NULL; } product = vici_message_create_from_data( this->writer->extract_buf(this->writer), TRUE); - this->writer->destroy(this->writer); - free(this); + destroy(this); return product; } @@ -245,6 +273,7 @@ vici_builder_t *vici_builder_create() .begin_list = _begin_list, .end_list = _end_list, .finalize = _finalize, + .destroy = _destroy, }, .writer = bio_writer_create(0), ); diff --git a/src/libcharon/plugins/vici/vici_builder.h b/src/libcharon/plugins/vici/vici_builder.h index 5a5cc8a03..f7d21eb8f 100644 --- a/src/libcharon/plugins/vici/vici_builder.h +++ b/src/libcharon/plugins/vici/vici_builder.h @@ -119,6 +119,14 @@ struct vici_builder_t { * @return vici message, NULL on error */ vici_message_t* (*finalize)(vici_builder_t *this); + + /** + * Destroy a vici builder without finalization. + * + * Note that finalize() already destroys the message, and calling destroy() + * is required only if the message does not get finalize()d. + */ + void (*destroy)(vici_builder_t *this); }; /** diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c index 113d48084..649161020 100644 --- a/src/libcharon/plugins/vici/vici_config.c +++ b/src/libcharon/plugins/vici/vici_config.c @@ -1551,8 +1551,8 @@ static void clear_start_action(private_vici_config_t *this, enumerator_t *enumerator, *children; child_sa_t *child_sa; ike_sa_t *ike_sa; - u_int32_t reqid = 0, *del; - array_t *reqids = NULL; + u_int32_t id = 0, *del; + array_t *ids = NULL; char *name; name = child_cfg->get_name(child_cfg); @@ -1568,23 +1568,23 @@ static void clear_start_action(private_vici_config_t *this, { if (streq(name, child_sa->get_name(child_sa))) { - reqid = child_sa->get_reqid(child_sa); - array_insert_create(&reqids, ARRAY_TAIL, &reqid); + id = child_sa->get_unique_id(child_sa); + array_insert_create(&ids, ARRAY_TAIL, &id); } } children->destroy(children); } enumerator->destroy(enumerator); - if (array_count(reqids)) + if (array_count(ids)) { - while (array_remove(reqids, ARRAY_HEAD, &del)) + while (array_remove(ids, ARRAY_HEAD, &del)) { DBG1(DBG_CFG, "closing '%s' #%u", name, *del); charon->controller->terminate_child(charon->controller, *del, NULL, NULL, 0); } - array_destroy(reqids); + array_destroy(ids); } break; case ACTION_ROUTE: @@ -1601,14 +1601,14 @@ static void clear_start_action(private_vici_config_t *this, { if (streq(name, child_sa->get_name(child_sa))) { - reqid = child_sa->get_reqid(child_sa); + id = child_sa->get_reqid(child_sa); break; } } enumerator->destroy(enumerator); - if (reqid) + if (id) { - charon->traps->uninstall(charon->traps, reqid); + charon->traps->uninstall(charon->traps, id); } break; } @@ -1751,7 +1751,8 @@ CALLBACK(config_sn, bool, .fragmentation = FRAGMENTATION_NO, .unique = UNIQUE_NO, .keyingtries = 1, - .rekey_time = LFT_DEFAULT_IKE_REKEY, + .rekey_time = LFT_UNDEFINED, + .reauth_time = LFT_UNDEFINED, .over_time = LFT_UNDEFINED, .rand_time = LFT_UNDEFINED, }; @@ -1809,6 +1810,20 @@ CALLBACK(config_sn, bool, peer.local_port = charon->socket->get_port(charon->socket, FALSE); } + if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED) + { + /* apply a default rekey time if no rekey/reauth time set */ + peer.rekey_time = LFT_DEFAULT_IKE_REKEY; + peer.reauth_time = 0; + } + if (peer.rekey_time == LFT_UNDEFINED) + { + peer.rekey_time = 0; + } + if (peer.reauth_time == LFT_UNDEFINED) + { + peer.reauth_time = 0; + } if (peer.over_time == LFT_UNDEFINED) { /* default over_time to 10% of rekey/reauth time if not given */ @@ -1816,9 +1831,17 @@ CALLBACK(config_sn, bool, } if (peer.rand_time == LFT_UNDEFINED) { - /* default rand_time to over_time if not given */ - peer.rand_time = min(peer.over_time, - max(peer.rekey_time, peer.reauth_time) / 2); + /* default rand_time to over_time if not given, but don't make it + * longer than half of rekey/rauth time */ + if (peer.rekey_time && peer.reauth_time) + { + peer.rand_time = min(peer.rekey_time, peer.reauth_time); + } + else + { + peer.rand_time = max(peer.rekey_time, peer.reauth_time); + } + peer.rand_time = min(peer.over_time, peer.rand_time / 2); } log_peer_data(&peer); diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c index 292a40032..01d503644 100644 --- a/src/libcharon/plugins/vici/vici_control.c +++ b/src/libcharon/plugins/vici/vici_control.c @@ -264,11 +264,11 @@ CALLBACK(terminate, vici_message_t*, { continue; } - if (child_id && child_sa->get_reqid(child_sa) != child_id) + if (child_id && child_sa->get_unique_id(child_sa) != child_id) { continue; } - current = child_sa->get_reqid(child_sa); + current = child_sa->get_unique_id(child_sa); array_insert(ids, ARRAY_TAIL, ¤t); } csas->destroy(csas); diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c index 8881feca9..af8bd283b 100644 --- a/src/libcharon/plugins/vici/vici_plugin.c +++ b/src/libcharon/plugins/vici/vici_plugin.c @@ -23,7 +23,6 @@ #include "vici_logger.h" #include <library.h> -#include <hydra.h> #include <daemon.h> typedef struct private_vici_plugin_t private_vici_plugin_t; @@ -104,8 +103,8 @@ static bool register_vici(private_vici_plugin_t *this, charon->backends->add_backend(charon->backends, &this->config->backend); - hydra->attributes->add_provider(hydra->attributes, - &this->attrs->provider); + charon->attributes->add_provider(charon->attributes, + &this->attrs->provider); charon->bus->add_logger(charon->bus, &this->logger->logger); return TRUE; } @@ -114,8 +113,8 @@ static bool register_vici(private_vici_plugin_t *this, else { charon->bus->remove_logger(charon->bus, &this->logger->logger); - hydra->attributes->remove_provider(hydra->attributes, - &this->attrs->provider); + charon->attributes->remove_provider(charon->attributes, + &this->attrs->provider); charon->backends->remove_backend(charon->backends, &this->config->backend); diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c index 54833abde..3e0d73cdf 100644 --- a/src/libcharon/plugins/vici/vici_query.c +++ b/src/libcharon/plugins/vici/vici_query.c @@ -63,11 +63,13 @@ static void list_child(private_vici_query_t *this, vici_builder_t *b, enumerator_t *enumerator; traffic_selector_t *ts; + b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child)); b->add_kv(b, "reqid", "%u", child->get_reqid(child)); b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child)); b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child)); if (child->get_state(child) == CHILD_INSTALLED || - child->get_state(child) == CHILD_REKEYING) + child->get_state(child) == CHILD_REKEYING || + child->get_state(child) == CHILD_REKEYED) { b->add_kv(b, "protocol", "%N", protocol_id_names, child->get_protocol(child)); @@ -507,11 +509,14 @@ static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b) certificate_t *cert; char *str; } v; + char buf[32]; + int i = 0; enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local); while (enumerator->enumerate(enumerator, &auth)) { - b->begin_section(b, local ? "local" : "remote"); + snprintf(buf, sizeof(buf), "%s-%d", local ? "local" : "remote", ++i); + b->begin_section(b, buf); rules = auth->create_enumerator(auth); while (rules->enumerate(rules, &rule, &v)) @@ -976,10 +981,10 @@ CALLBACK(stats, vici_message_t*, struct mallinfo mi = mallinfo(); b->begin_section(b, "mallinfo"); - b->add_kv(b, "sbrk", "%d", mi.arena); - b->add_kv(b, "mmap", "%d", mi.hblkhd); - b->add_kv(b, "used", "%d", mi.uordblks); - b->add_kv(b, "free", "%d", mi.fordblks); + b->add_kv(b, "sbrk", "%u", mi.arena); + b->add_kv(b, "mmap", "%u", mi.hblkhd); + b->add_kv(b, "used", "%u", mi.uordblks); + b->add_kv(b, "free", "%u", mi.fordblks); b->end_section(b); } #endif /* HAVE_MALLINFO */ diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in index b1cc1d118..e400d9f35 100644 --- a/src/libcharon/plugins/whitelist/Makefile.in +++ b/src/libcharon/plugins/whitelist/Makefile.in @@ -236,6 +236,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -296,10 +297,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -373,6 +376,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in index e393ee163..a9684455d 100644 --- a/src/libcharon/plugins/xauth_eap/Makefile.in +++ b/src/libcharon/plugins/xauth_eap/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in index f0e772700..5170c924f 100644 --- a/src/libcharon/plugins/xauth_generic/Makefile.in +++ b/src/libcharon/plugins/xauth_generic/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in index a4c1aaeb2..087f5b350 100644 --- a/src/libcharon/plugins/xauth_noauth/Makefile.in +++ b/src/libcharon/plugins/xauth_noauth/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in index 296ccaa1c..29441bcb5 100644 --- a/src/libcharon/plugins/xauth_pam/Makefile.in +++ b/src/libcharon/plugins/xauth_pam/Makefile.in @@ -229,6 +229,7 @@ DLLIB = @DLLIB@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ @@ -289,10 +290,12 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ RUBY = @RUBY@ @@ -366,6 +369,8 @@ json_CFLAGS = @json_CFLAGS@ json_LIBS = @json_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ linux_headers = @linux_headers@ localedir = @localedir@ localstatedir = @localstatedir@ diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c index fb480eee2..c8a9c17de 100644 --- a/src/libcharon/processing/jobs/adopt_children_job.c +++ b/src/libcharon/processing/jobs/adopt_children_job.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2012 Martin Willi * Copyright (C) 2012 revosec AG * @@ -54,10 +57,10 @@ METHOD(job_t, execute, job_requeue_t, private_adopt_children_job_t *this) { identification_t *my_id, *other_id, *xauth; - host_t *me, *other; + host_t *me, *other, *vip; peer_cfg_t *cfg; - linked_list_t *children; - enumerator_t *enumerator, *childenum; + linked_list_t *children, *vips; + enumerator_t *enumerator, *subenum; ike_sa_id_t *id; ike_sa_t *ike_sa; child_sa_t *child_sa; @@ -81,7 +84,8 @@ METHOD(job_t, execute, job_requeue_t, charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - /* find old SA to adopt children from */ + /* find old SA to adopt children and virtual IPs from */ + vips = linked_list_create(); children = linked_list_create(); enumerator = charon->ike_sa_manager->create_id_enumerator( charon->ike_sa_manager, my_id, xauth, @@ -102,18 +106,29 @@ METHOD(job_t, execute, job_requeue_t, other_id->equals(other_id, ike_sa->get_other_id(ike_sa)) && cfg->equals(cfg, ike_sa->get_peer_cfg(ike_sa))) { - childenum = ike_sa->create_child_sa_enumerator(ike_sa); - while (childenum->enumerate(childenum, &child_sa)) + subenum = ike_sa->create_child_sa_enumerator(ike_sa); + while (subenum->enumerate(subenum, &child_sa)) { - ike_sa->remove_child_sa(ike_sa, childenum); + ike_sa->remove_child_sa(ike_sa, subenum); children->insert_last(children, child_sa); } - childenum->destroy(childenum); - if (children->get_count(children)) + subenum->destroy(subenum); + + subenum = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); + while (subenum->enumerate(subenum, &vip)) + { + vips->insert_last(vips, vip->clone(vip)); + } + subenum->destroy(subenum); + /* this does not release the addresses, which is good, but + * it does trigger an assign_vips(FALSE) event, so we also + * trigger one below */ + ike_sa->clear_virtual_ips(ike_sa, FALSE); + if (children->get_count(children) || vips->get_count(vips)) { DBG1(DBG_IKE, "detected reauth of existing IKE_SA, " - "adopting %d children", - children->get_count(children)); + "adopting %d children and %d virtual IPs", + children->get_count(children), vips->get_count(vips)); } ike_sa->set_state(ike_sa, IKE_DELETING); charon->bus->ike_updown(charon->bus, ike_sa, FALSE); @@ -125,7 +140,7 @@ METHOD(job_t, execute, job_requeue_t, charon->ike_sa_manager->checkin( charon->ike_sa_manager, ike_sa); } - if (children->get_count(children)) + if (children->get_count(children) || vips->get_count(vips)) { break; } @@ -140,7 +155,7 @@ METHOD(job_t, execute, job_requeue_t, xauth->destroy(xauth); cfg->destroy(cfg); - if (children->get_count(children)) + if (children->get_count(children) || vips->get_count(vips)) { /* adopt children by new SA */ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, @@ -152,10 +167,27 @@ METHOD(job_t, execute, job_requeue_t, { ike_sa->add_child_sa(ike_sa, child_sa); } + if (vips->get_count(vips)) + { + while (vips->remove_first(vips, (void**)&vip) == SUCCESS) + { + ike_sa->add_virtual_ip(ike_sa, FALSE, vip); + vip->destroy(vip); + } + charon->bus->assign_vips(charon->bus, ike_sa, TRUE); + } charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } } children->destroy_offset(children, offsetof(child_sa_t, destroy)); + /* FIXME: If we still have addresses here it means we weren't able to + * find the new SA anymore (while not very likely during a proper + * reauthentication, this theoretically could happen because the SA is + * not locked while we search for the old one). So the addresses here + * should be released properly to avoid leaking these leases. This is + * currently not possible, though, due to the changed interface of + * release_address(), which now takes a complete IKE_SA object. */ + vips->destroy_offset(vips, offsetof(host_t, destroy)); if (array_count(this->tasks)) { diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.c b/src/libcharon/processing/jobs/delete_child_sa_job.c index 9afbac02b..0d85883be 100644 --- a/src/libcharon/processing/jobs/delete_child_sa_job.c +++ b/src/libcharon/processing/jobs/delete_child_sa_job.c @@ -31,11 +31,6 @@ struct private_delete_child_sa_job_t { delete_child_sa_job_t public; /** - * reqid of the CHILD_SA - */ - u_int32_t reqid; - - /** * protocol of the CHILD_SA (ESP/AH) */ protocol_id_t protocol; @@ -46,6 +41,11 @@ struct private_delete_child_sa_job_t { u_int32_t spi; /** + * SA destination address + */ + host_t *dst; + + /** * Delete for an expired CHILD_SA */ bool expired; @@ -54,6 +54,7 @@ struct private_delete_child_sa_job_t { METHOD(job_t, destroy, void, private_delete_child_sa_job_t *this) { + this->dst->destroy(this->dst); free(this); } @@ -62,12 +63,12 @@ METHOD(job_t, execute, job_requeue_t, { ike_sa_t *ike_sa; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - this->reqid, TRUE); + ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager, + this->protocol, this->spi, this->dst, NULL); if (ike_sa == NULL) { - DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for delete", - this->reqid); + DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for delete", + protocol_id_names, this->protocol, htonl(this->spi), this->dst); } else { @@ -87,8 +88,8 @@ METHOD(job_t, get_priority, job_priority_t, /* * Described in header */ -delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, u_int32_t spi, bool expired) +delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst, bool expired) { private_delete_child_sa_job_t *this; @@ -100,12 +101,11 @@ delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, .destroy = _destroy, }, }, - .reqid = reqid, .protocol = protocol, .spi = spi, + .dst = dst->clone(dst), .expired = expired, ); return &this->public; } - diff --git a/src/libcharon/processing/jobs/delete_child_sa_job.h b/src/libcharon/processing/jobs/delete_child_sa_job.h index be6d578bc..6fa53644c 100644 --- a/src/libcharon/processing/jobs/delete_child_sa_job.h +++ b/src/libcharon/processing/jobs/delete_child_sa_job.h @@ -44,16 +44,13 @@ struct delete_child_sa_job_t { /** * Creates a job of type DELETE_CHILD_SA. * - * The CHILD_SA is identified by its reqid, protocol (AH/ESP) and its - * inbound SPI. - * - * @param reqid reqid of the CHILD_SA, as used in kernel * @param protocol protocol of the CHILD_SA * @param spi security parameter index of the CHILD_SA + * @param dst SA destination address * @param expired TRUE if CHILD_SA already expired * @return delete_child_sa_job_t object */ -delete_child_sa_job_t *delete_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, u_int32_t spi, bool expired); +delete_child_sa_job_t *delete_child_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst, bool expired); #endif /** DELETE_CHILD_SA_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/dpd_timeout_job.c b/src/libcharon/processing/jobs/dpd_timeout_job.c index 9cdce5cab..4c88c13e2 100644 --- a/src/libcharon/processing/jobs/dpd_timeout_job.c +++ b/src/libcharon/processing/jobs/dpd_timeout_job.c @@ -63,6 +63,12 @@ METHOD(job_t, execute, job_requeue_t, this->ike_sa_id); if (ike_sa) { + if (ike_sa->get_state(ike_sa) == IKE_PASSIVE) + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + return JOB_REQUEUE_NONE; + } + use_time = ike_sa->get_statistic(ike_sa, STAT_INBOUND); enumerator = ike_sa->create_child_sa_enumerator(ike_sa); diff --git a/src/libcharon/processing/jobs/inactivity_job.c b/src/libcharon/processing/jobs/inactivity_job.c index 197733979..f0f90eedf 100644 --- a/src/libcharon/processing/jobs/inactivity_job.c +++ b/src/libcharon/processing/jobs/inactivity_job.c @@ -30,9 +30,9 @@ struct private_inactivity_job_t { inactivity_job_t public; /** - * Reqid of CHILD_SA to check + * Unique CHILD_SA identifier to check */ - u_int32_t reqid; + u_int32_t id; /** * Inactivity timeout @@ -57,8 +57,8 @@ METHOD(job_t, execute, job_requeue_t, ike_sa_t *ike_sa; u_int32_t reschedule = 0; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - this->reqid, TRUE); + ike_sa = charon->child_sa_manager->checkout_by_id(charon->child_sa_manager, + this->id, NULL); if (ike_sa) { enumerator_t *enumerator; @@ -69,9 +69,9 @@ METHOD(job_t, execute, job_requeue_t, status_t status = SUCCESS; enumerator = ike_sa->create_child_sa_enumerator(ike_sa); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + while (enumerator->enumerate(enumerator, &child_sa)) { - if (child_sa->get_reqid(child_sa) == this->reqid) + if (child_sa->get_unique_id(child_sa) == this->id) { time_t in, out, install, diff; @@ -136,7 +136,7 @@ METHOD(job_t, get_priority, job_priority_t, /** * See header */ -inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout, +inactivity_job_t *inactivity_job_create(u_int32_t unique_id, u_int32_t timeout, bool close_ike) { private_inactivity_job_t *this; @@ -149,7 +149,7 @@ inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout, .destroy = _destroy, }, }, - .reqid = reqid, + .id = unique_id, .timeout = timeout, .close_ike = close_ike, ); diff --git a/src/libcharon/processing/jobs/inactivity_job.h b/src/libcharon/processing/jobs/inactivity_job.h index 890f7704b..ff19fe560 100644 --- a/src/libcharon/processing/jobs/inactivity_job.h +++ b/src/libcharon/processing/jobs/inactivity_job.h @@ -42,12 +42,12 @@ struct inactivity_job_t { /** * Create a inactivity_job instance. * - * @param reqid reqid of CHILD_SA to check for inactivity + * @param unique_id unique CHILD_SA identifier to check for inactivity * @param timeout inactivity timeout in s * @param close_ike close IKE_SA if the last remaining CHILD_SA is inactive? * @return inactivity checking job */ -inactivity_job_t *inactivity_job_create(u_int32_t reqid, u_int32_t timeout, +inactivity_job_t *inactivity_job_create(u_int32_t unique_id, u_int32_t timeout, bool close_ike); #endif /** INACTIVITY_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/initiate_tasks_job.c b/src/libcharon/processing/jobs/initiate_tasks_job.c new file mode 100644 index 000000000..001e71fd1 --- /dev/null +++ b/src/libcharon/processing/jobs/initiate_tasks_job.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2015 Martin Willi + * Copyright (C) 2015 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 <stdlib.h> + +#include "initiate_tasks_job.h" + +#include <sa/ike_sa.h> +#include <daemon.h> + + +typedef struct private_initiate_tasks_job_t private_initiate_tasks_job_t; + +/** + * Private data of an initiate_tasks_job_t Object + */ +struct private_initiate_tasks_job_t { + + /** + * Public initiate_tasks_job_t interface + */ + initiate_tasks_job_t public; + + /** + * ID of the IKE_SA to trigger task initiation + */ + ike_sa_id_t *ike_sa_id; +}; + +METHOD(job_t, destroy, void, + private_initiate_tasks_job_t *this) +{ + this->ike_sa_id->destroy(this->ike_sa_id); + free(this); +} + +METHOD(job_t, execute, job_requeue_t, + private_initiate_tasks_job_t *this) +{ + ike_sa_t *ike_sa; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + this->ike_sa_id); + if (ike_sa) + { + if (ike_sa->initiate(ike_sa, NULL, 0, NULL, NULL) == DESTROY_ME) + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, + ike_sa); + } + else + { + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + } + return JOB_REQUEUE_NONE; +} + +METHOD(job_t, get_priority, job_priority_t, + private_initiate_tasks_job_t *this) +{ + return JOB_PRIO_MEDIUM; +} + +/* + * Described in header + */ +initiate_tasks_job_t *initiate_tasks_job_create(ike_sa_id_t *ike_sa_id) +{ + private_initiate_tasks_job_t *this; + + INIT(this, + .public = { + .job_interface = { + .execute = _execute, + .get_priority = _get_priority, + .destroy = _destroy, + }, + }, + .ike_sa_id = ike_sa_id->clone(ike_sa_id), + ); + + return &this->public; +} diff --git a/src/libcharon/processing/jobs/initiate_tasks_job.h b/src/libcharon/processing/jobs/initiate_tasks_job.h new file mode 100644 index 000000000..071497843 --- /dev/null +++ b/src/libcharon/processing/jobs/initiate_tasks_job.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Martin Willi + * Copyright (C) 2015 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 initiate_tasks_job initiate_tasks_job + * @{ @ingroup cjobs + */ + +#ifndef INITIATE_TASKS_JOB_H_ +#define INITIATE_TASKS_JOB_H_ + +typedef struct initiate_tasks_job_t initiate_tasks_job_t; + +#include <library.h> +#include <processing/jobs/job.h> +#include <sa/ike_sa_id.h> + +/** + * Job triggering initiation of any queued IKE_SA tasks. + */ +struct initiate_tasks_job_t { + + /** + * Implements job_t interface + */ + job_t job_interface; +}; + +/** + * Creates a job to trigger IKE_SA task initiation. + * + * @param ike_sa_id ID of IKE_SA to trigger tasks for (gets cloned) + * @return job instance + */ +initiate_tasks_job_t *initiate_tasks_job_create(ike_sa_id_t *ike_sa_id); + +#endif /** INITIATE_TASKS_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/migrate_job.c b/src/libcharon/processing/jobs/migrate_job.c index 2ebfc6714..097dbdffd 100644 --- a/src/libcharon/processing/jobs/migrate_job.c +++ b/src/libcharon/processing/jobs/migrate_job.c @@ -70,29 +70,34 @@ METHOD(job_t, destroy, void, METHOD(job_t, execute, job_requeue_t, private_migrate_job_t *this) { - ike_sa_t *ike_sa = NULL; + enumerator_t *ike_sas, *children; + ike_sa_t *ike_sa; - if (this->reqid) + ike_sas = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager, + TRUE); + while (ike_sas->enumerate(ike_sas, &ike_sa)) { - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - this->reqid, TRUE); - } - if (ike_sa) - { - enumerator_t *children, *enumerator; - child_sa_t *child_sa; - host_t *host; + child_sa_t *current, *child_sa = NULL; linked_list_t *vips; + status_t status; + host_t *host; children = ike_sa->create_child_sa_enumerator(ike_sa); - while (children->enumerate(children, (void**)&child_sa)) + while (children->enumerate(children, ¤t)) { - if (child_sa->get_reqid(child_sa) == this->reqid) + if (current->get_reqid(current) == this->reqid) { + child_sa = current; break; } } children->destroy(children); + + if (!child_sa) + { + continue; + } + DBG2(DBG_JOB, "found CHILD_SA with reqid {%d}", this->reqid); ike_sa->set_kmaddress(ike_sa, this->local, this->remote); @@ -105,27 +110,28 @@ METHOD(job_t, execute, job_requeue_t, host->set_port(host, IKEV2_UDP_PORT); ike_sa->set_other_host(ike_sa, host); - vips = linked_list_create(); - enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE); - while (enumerator->enumerate(enumerator, &host)) - { - vips->insert_last(vips, host); - } - enumerator->destroy(enumerator); + vips = linked_list_create_from_enumerator( + ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE)); - if (child_sa->update(child_sa, this->local, this->remote, vips, - ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED) + status = child_sa->update(child_sa, this->local, this->remote, vips, + ike_sa->has_condition(ike_sa, COND_NAT_ANY)); + switch (status) { - ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + case NOT_SUPPORTED: + ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + break; + case SUCCESS: + charon->child_sa_manager->remove(charon->child_sa_manager, + child_sa); + charon->child_sa_manager->add(charon->child_sa_manager, + child_sa, ike_sa); + default: + break; } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); vips->destroy(vips); } - else - { - DBG1(DBG_JOB, "no CHILD_SA found with reqid {%d}", this->reqid); - } + ike_sas->destroy(ike_sas); return JOB_REQUEUE_NONE; } diff --git a/src/libcharon/processing/jobs/migrate_job.h b/src/libcharon/processing/jobs/migrate_job.h index 30c0ad0ac..0f2b9aaad 100644 --- a/src/libcharon/processing/jobs/migrate_job.h +++ b/src/libcharon/processing/jobs/migrate_job.h @@ -46,7 +46,7 @@ struct migrate_job_t { * * We use the reqid or the traffic selectors to find a matching CHILD_SA. * - * @param reqid reqid of the CHILD_SA to acquire + * @param reqid reqid of the CHILD_SA to migrate * @param src_ts source traffic selector to be used in the policy * @param dst_ts destination traffic selector to be used in the policy * @param dir direction of the policy (in|out) diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c index 1bf8dc0cb..8f17d39ab 100644 --- a/src/libcharon/processing/jobs/rekey_child_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c @@ -24,17 +24,13 @@ typedef struct private_rekey_child_sa_job_t private_rekey_child_sa_job_t; * Private data of an rekey_child_sa_job_t object. */ struct private_rekey_child_sa_job_t { + /** * Public rekey_child_sa_job_t interface. */ rekey_child_sa_job_t public; /** - * reqid of the child to rekey - */ - u_int32_t reqid; - - /** * protocol of the CHILD_SA (ESP/AH) */ protocol_id_t protocol; @@ -43,11 +39,17 @@ struct private_rekey_child_sa_job_t { * inbound SPI of the CHILD_SA */ u_int32_t spi; + + /** + * SA destination address + */ + host_t *dst; }; METHOD(job_t, destroy, void, private_rekey_child_sa_job_t *this) { + this->dst->destroy(this->dst); free(this); } @@ -56,12 +58,12 @@ METHOD(job_t, execute, job_requeue_t, { ike_sa_t *ike_sa; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - this->reqid, TRUE); + ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager, + this->protocol, this->spi, this->dst, NULL); if (ike_sa == NULL) { - DBG2(DBG_JOB, "CHILD_SA with reqid %d not found for rekeying", - this->reqid); + DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for rekey", + protocol_id_names, this->protocol, htonl(this->spi), this->dst); } else { @@ -80,9 +82,8 @@ METHOD(job_t, get_priority, job_priority_t, /* * Described in header */ -rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, - u_int32_t spi) +rekey_child_sa_job_t *rekey_child_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst) { private_rekey_child_sa_job_t *this; @@ -94,9 +95,9 @@ rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, .destroy = _destroy, }, }, - .reqid = reqid, .protocol = protocol, .spi = spi, + .dst = dst->clone(dst), ); return &this->public; diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.h b/src/libcharon/processing/jobs/rekey_child_sa_job.h index fcbe65a06..364bb5ae7 100644 --- a/src/libcharon/processing/jobs/rekey_child_sa_job.h +++ b/src/libcharon/processing/jobs/rekey_child_sa_job.h @@ -43,15 +43,11 @@ struct rekey_child_sa_job_t { /** * Creates a job of type REKEY_CHILD_SA. * - * The CHILD_SA is identified by its protocol (AH/ESP) and its - * inbound SPI. - * - * @param reqid reqid of the CHILD_SA to rekey * @param protocol protocol of the CHILD_SA * @param spi security parameter index of the CHILD_SA + * @param dst SA destination address * @return rekey_child_sa_job_t object */ -rekey_child_sa_job_t *rekey_child_sa_job_create(u_int32_t reqid, - protocol_id_t protocol, - u_int32_t spi); +rekey_child_sa_job_t *rekey_child_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst); #endif /** REKEY_CHILD_SA_JOB_H_ @}*/ diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c index 516dc5dd5..403d826a3 100644 --- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c +++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c @@ -67,7 +67,8 @@ static u_int32_t get_retry_delay(ike_sa_t *ike_sa) enumerator = ike_sa->create_child_sa_enumerator(ike_sa); while (enumerator->enumerate(enumerator, &child_sa)) { - if (child_sa->get_state(child_sa) != CHILD_INSTALLED) + if (child_sa->get_state(child_sa) != CHILD_INSTALLED && + child_sa->get_state(child_sa) != CHILD_REKEYED) { retry = RETRY_INTERVAL - (random() % RETRY_JITTER); DBG1(DBG_IKE, "unable to reauthenticate in CHILD_SA %N state, " diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c index e6d7da2c6..862506d90 100644 --- a/src/libcharon/processing/jobs/update_sa_job.c +++ b/src/libcharon/processing/jobs/update_sa_job.c @@ -27,15 +27,26 @@ typedef struct private_update_sa_job_t private_update_sa_job_t; * Private data of an update_sa_job_t Object */ struct private_update_sa_job_t { + /** * public update_sa_job_t interface */ update_sa_job_t public; /** - * reqid of the CHILD_SA + * protocol of the CHILD_SA (ESP/AH) + */ + protocol_id_t protocol; + + /** + * SPI of the CHILD_SA */ - u_int32_t reqid; + u_int32_t spi; + + /** + * Old SA destination address + */ + host_t *dst; /** * New SA address and port @@ -46,6 +57,7 @@ struct private_update_sa_job_t { METHOD(job_t, destroy, void, private_update_sa_job_t *this) { + this->dst->destroy(this->dst); this->new->destroy(this->new); free(this); } @@ -55,11 +67,12 @@ METHOD(job_t, execute, job_requeue_t, { ike_sa_t *ike_sa; - ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, - this->reqid, TRUE); + ike_sa = charon->child_sa_manager->checkout(charon->child_sa_manager, + this->protocol, this->spi, this->dst, NULL); if (ike_sa == NULL) { - DBG1(DBG_JOB, "CHILD_SA with reqid %d not found for update", this->reqid); + DBG1(DBG_JOB, "CHILD_SA %N/0x%08x/%H not found for update", + protocol_id_names, this->protocol, htonl(this->spi), this->dst); } else { @@ -78,7 +91,8 @@ METHOD(job_t, get_priority, job_priority_t, /* * Described in header */ -update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new) +update_sa_job_t *update_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst, host_t *new) { private_update_sa_job_t *this; @@ -90,10 +104,11 @@ update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new) .destroy = _destroy, }, }, - .reqid = reqid, - .new = new, + .protocol = protocol, + .spi = spi, + .dst = dst->clone(dst), + .new = new->clone(new), ); return &this->public; } - diff --git a/src/libcharon/processing/jobs/update_sa_job.h b/src/libcharon/processing/jobs/update_sa_job.h index 55a3df83e..9c19f5b6e 100644 --- a/src/libcharon/processing/jobs/update_sa_job.h +++ b/src/libcharon/processing/jobs/update_sa_job.h @@ -26,6 +26,7 @@ typedef struct update_sa_job_t update_sa_job_t; #include <library.h> #include <networking/host.h> #include <processing/jobs/job.h> +#include <config/proposal.h> /** * Update the addresses of an IKE and its CHILD_SAs. @@ -41,10 +42,13 @@ struct update_sa_job_t { /** * Creates a job to update IKE and CHILD_SA addresses. * - * @param reqid reqid of the CHILD_SA + * @param protocol IPsec protocol of SA to update + * @param spi SPI of SA to update + * @param dst old destination host of SA to update * @param new new address and port * @return update_sa_job_t object */ -update_sa_job_t *update_sa_job_create(u_int32_t reqid, host_t *new); +update_sa_job_t *update_sa_job_create(protocol_id_t protocol, + u_int32_t spi, host_t *dst, host_t *new); #endif /** UPDATE_SA_JOB_H_ @}*/ diff --git a/src/libcharon/sa/authenticator.c b/src/libcharon/sa/authenticator.c index 8571274ac..6c3681a2d 100644 --- a/src/libcharon/sa/authenticator.c +++ b/src/libcharon/sa/authenticator.c @@ -31,12 +31,14 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS, "RSA signature", "pre-shared key", "DSS signature"); -ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS, +ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_DS, AUTH_DSS, "ECDSA-256 signature", "ECDSA-384 signature", "ECDSA-521 signature", - "secure password method"); -ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_GSPM, + "secure password method", + "NULL authentication", + "digital signature"); +ENUM_NEXT(auth_method_names, AUTH_XAUTH_INIT_PSK, AUTH_HYBRID_RESP_RSA, AUTH_DS, "XAuthInitPSK", "XAuthRespPSK", "XAuthInitRSA", @@ -99,6 +101,7 @@ authenticator_t *authenticator_create_verifier( case AUTH_ECDSA_256: case AUTH_ECDSA_384: case AUTH_ECDSA_521: + case AUTH_DS: return (authenticator_t*)pubkey_authenticator_create_verifier(ike_sa, sent_nonce, received_init, reserved); case AUTH_PSK: diff --git a/src/libcharon/sa/authenticator.h b/src/libcharon/sa/authenticator.h index 914f42d9d..97c042e71 100644 --- a/src/libcharon/sa/authenticator.h +++ b/src/libcharon/sa/authenticator.h @@ -80,6 +80,16 @@ enum auth_method_t { AUTH_GSPM = 12, /** + * NULL Authentication Method as specified in draft-ietf-ipsecme-ikev2-null-auth + */ + AUTH_NULL = 13, + + /** + * Digital Signature as specified in RFC 7427 + */ + AUTH_DS = 14, + + /** * IKEv1 initiator XAUTH with PSK, outside of IANA range */ AUTH_XAUTH_INIT_PSK = 256, diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index a96ab4e90..e0db2e655 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -34,6 +34,8 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING, "INSTALLED", "UPDATING", "REKEYING", + "REKEYED", + "RETRYING", "DELETING", "DESTROYING", ); @@ -100,6 +102,16 @@ struct private_child_sa_t { u_int32_t reqid; /** + * Did we allocate/confirm and must release the reqid? + */ + bool reqid_allocated; + + /* + * Unique CHILD_SA identifier + */ + u_int32_t unique_id; + + /** * inbound mark used for this child_sa */ mark_t mark_in; @@ -228,6 +240,12 @@ METHOD(child_sa_t, get_reqid, u_int32_t, return this->reqid; } +METHOD(child_sa_t, get_unique_id, u_int32_t, + private_child_sa_t *this) +{ + return this->unique_id; +} + METHOD(child_sa_t, get_config, child_cfg_t*, private_child_sa_t *this) { @@ -602,7 +620,7 @@ METHOD(child_sa_t, alloc_spi, u_int32_t, { if (hydra->kernel_interface->get_spi(hydra->kernel_interface, this->other_addr, this->my_addr, - proto_ike2ip(protocol), this->reqid, + proto_ike2ip(protocol), &this->my_spi) == SUCCESS) { /* if we allocate a SPI, but then are unable to establish the SA, we @@ -618,7 +636,7 @@ METHOD(child_sa_t, alloc_cpi, u_int16_t, { if (hydra->kernel_interface->get_cpi(hydra->kernel_interface, this->other_addr, this->my_addr, - this->reqid, &this->my_cpi) == SUCCESS) + &this->my_cpi) == SUCCESS) { return this->my_cpi; } @@ -632,7 +650,7 @@ METHOD(child_sa_t, install, status_t, { u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size; u_int16_t esn = NO_EXT_SEQ_NUMBERS; - traffic_selector_t *src_ts = NULL, *dst_ts = NULL; + linked_list_t *src_ts = NULL, *dst_ts = NULL; time_t now; lifetime_cfg_t *lifetime; u_int32_t tfc = 0; @@ -680,6 +698,18 @@ METHOD(child_sa_t, install, status_t, this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS, &esn, NULL); + if (!this->reqid_allocated) + { + status = hydra->kernel_interface->alloc_reqid(hydra->kernel_interface, + my_ts, other_ts, this->mark_in, this->mark_out, + &this->reqid); + if (status != SUCCESS) + { + return status; + } + this->reqid_allocated = TRUE; + } + lifetime = this->config->get_lifetime(this->config); now = time_monotonic(NULL); @@ -704,18 +734,16 @@ METHOD(child_sa_t, install, status_t, lifetime->time.rekey = 0; } - /* BEET requires the bound address from the traffic selectors. - * TODO: We add just the first traffic selector for now, as the - * kernel accepts a single TS per SA only */ + /* BEET requires the bound address from the traffic selectors */ if (inbound) { - my_ts->get_first(my_ts, (void**)&dst_ts); - other_ts->get_first(other_ts, (void**)&src_ts); + dst_ts = my_ts; + src_ts = other_ts; } else { - my_ts->get_first(my_ts, (void**)&src_ts); - other_ts->get_first(other_ts, (void**)&dst_ts); + src_ts = my_ts; + dst_ts = other_ts; } status = hydra->kernel_interface->add_sa(hydra->kernel_interface, @@ -723,7 +751,7 @@ METHOD(child_sa_t, install, status_t, inbound ? this->mark_in : this->mark_out, tfc, lifetime, enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi, this->config->get_replay_window(this->config), - initiator, this->encap, esn, update, src_ts, dst_ts); + initiator, this->encap, esn, inbound, update, src_ts, dst_ts); free(lifetime); @@ -798,6 +826,19 @@ METHOD(child_sa_t, add_policies, status_t, traffic_selector_t *my_ts, *other_ts; status_t status = SUCCESS; + if (!this->reqid_allocated) + { + /* trap policy, get or confirm reqid */ + status = hydra->kernel_interface->alloc_reqid( + hydra->kernel_interface, my_ts_list, other_ts_list, + this->mark_in, this->mark_out, &this->reqid); + if (status != SUCCESS) + { + return status; + } + this->reqid_allocated = TRUE; + } + /* apply traffic selectors */ enumerator = my_ts_list->create_enumerator(my_ts_list); while (enumerator->enumerate(enumerator, &my_ts)) @@ -805,12 +846,15 @@ METHOD(child_sa_t, add_policies, status_t, array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts)); } enumerator->destroy(enumerator); + array_sort(this->my_ts, (void*)traffic_selector_cmp, NULL); + enumerator = other_ts_list->create_enumerator(other_ts_list); while (enumerator->enumerate(enumerator, &other_ts)) { array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts)); } enumerator->destroy(enumerator); + array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL); if (this->config->install_policy(this->config)) { @@ -1071,6 +1115,22 @@ METHOD(child_sa_t, destroy, void, set_state(this, CHILD_DESTROYING); + if (this->config->install_policy(this->config)) + { + /* delete all policies in the kernel */ + enumerator = create_policy_enumerator(this); + while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) + { + del_policies_internal(this, my_ts, other_ts, priority); + if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update()) + { + del_policies_internal(this, my_ts, other_ts, + POLICY_PRIORITY_FALLBACK); + } + } + enumerator->destroy(enumerator); + } + /* delete SAs in the kernel, if they are set up */ if (this->my_spi) { @@ -1087,20 +1147,13 @@ METHOD(child_sa_t, destroy, void, this->mark_out); } - if (this->config->install_policy(this->config)) + if (this->reqid_allocated) { - /* delete all policies in the kernel */ - enumerator = create_policy_enumerator(this); - while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) + if (hydra->kernel_interface->release_reqid(hydra->kernel_interface, + this->reqid, this->mark_in, this->mark_out) != SUCCESS) { - del_policies_internal(this, my_ts, other_ts, priority); - if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update()) - { - del_policies_internal(this, my_ts, other_ts, - POLICY_PRIORITY_FALLBACK); - } + DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid); } - enumerator->destroy(enumerator); } array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy)); @@ -1151,15 +1204,17 @@ static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local) * Described in header. */ child_sa_t * child_sa_create(host_t *me, host_t* other, - child_cfg_t *config, u_int32_t rekey, bool encap) + child_cfg_t *config, u_int32_t rekey, bool encap, + u_int mark_in, u_int mark_out) { - static refcount_t reqid = 0; private_child_sa_t *this; + static refcount_t unique_id = 0, unique_mark = 0, mark; INIT(this, .public = { .get_name = _get_name, .get_reqid = _get_reqid, + .get_unique_id = _get_unique_id, .get_config = _get_config, .get_state = _get_state, .set_state = _set_state, @@ -1201,6 +1256,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, .close_action = config->get_close_action(config), .dpd_action = config->get_dpd_action(config), .reqid = config->get_reqid(config), + .unique_id = ref_get(&unique_id), .mark_in = config->get_mark(config, TRUE), .mark_out = config->get_mark(config, FALSE), .install_time = time_monotonic(NULL), @@ -1209,9 +1265,37 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->config = config; config->get_ref(config); + if (mark_in) + { + this->mark_in.value = mark_in; + } + if (mark_out) + { + this->mark_out.value = mark_out; + } + if (this->mark_in.value == MARK_UNIQUE || + this->mark_out.value == MARK_UNIQUE) + { + mark = ref_get(&unique_mark); + if (this->mark_in.value == MARK_UNIQUE) + { + this->mark_in.value = mark; + } + if (this->mark_out.value == MARK_UNIQUE) + { + this->mark_out.value = mark; + } + } + if (!this->reqid) { - /* reuse old reqid if we are rekeying an existing CHILD_SA */ + /* reuse old reqid if we are rekeying an existing CHILD_SA. While the + * reqid cache would find the same reqid for our selectors, this does + * not work in a special case: If an SA is triggered by a trap policy, + * but the negotiated SA gets narrowed, we still must reuse the same + * reqid to successfully "trigger" the SA on the kernel level. Rekeying + * such an SA requires an explicit reqid, as the cache currently knows + * the original selectors only for that reqid. */ if (rekey) { this->reqid = rekey; @@ -1219,22 +1303,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, else { this->reqid = charon->traps->find_reqid(charon->traps, config); - if (!this->reqid) - { - this->reqid = ref_get(&reqid); - } } } - if (this->mark_in.value == MARK_REQID) - { - this->mark_in.value = this->reqid; - } - if (this->mark_out.value == MARK_REQID) - { - this->mark_out.value = this->reqid; - } - /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */ if (config->get_mode(config) == MODE_TRANSPORT && config->use_proxy_mode(config)) diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h index a0c6c357f..debe8eb2c 100644 --- a/src/libcharon/sa/child_sa.h +++ b/src/libcharon/sa/child_sa.h @@ -68,6 +68,16 @@ enum child_sa_state_t { CHILD_REKEYING, /** + * CHILD_SA that was rekeyed, but stays installed + */ + CHILD_REKEYED, + + /** + * CHILD_SA negotiation failed, but gets retried + */ + CHILD_RETRYING, + + /** * CHILD_SA in progress of delete */ CHILD_DELETING, @@ -121,6 +131,16 @@ struct child_sa_t { u_int32_t (*get_reqid)(child_sa_t *this); /** + * Get the unique numerical identifier for this CHILD_SA. + * + * While the same reqid might be shared between multiple SAs, the unique_id + * is truly unique for all CHILD_SA instances. + * + * @return unique CHILD_SA identifier + */ + u_int32_t (*get_unique_id)(child_sa_t *this); + + /** * Get the config used to set up this child sa. * * @return child_cfg @@ -379,9 +399,12 @@ struct child_sa_t { * @param config config to use for this CHILD_SA * @param reqid reqid of old CHILD_SA when rekeying, 0 otherwise * @param encap TRUE to enable UDP encapsulation (NAT traversal) + * @param mark_in explicit inbound mark value to use, 0 for config + * @param mark_out explicit outbound mark value to use, 0 for config * @return child_sa_t object */ child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config, - u_int32_t reqid, bool encap); + u_int32_t reqid, bool encap, + u_int mark_in, u_int mark_out); #endif /** CHILD_SA_H_ @}*/ diff --git a/src/libcharon/sa/child_sa_manager.c b/src/libcharon/sa/child_sa_manager.c new file mode 100644 index 000000000..071a119da --- /dev/null +++ b/src/libcharon/sa/child_sa_manager.c @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 "child_sa_manager.h" + +#include <daemon.h> +#include <threading/mutex.h> +#include <collections/hashtable.h> + +typedef struct private_child_sa_manager_t private_child_sa_manager_t; + +/** + * Private data of an child_sa_manager_t object. + */ +struct private_child_sa_manager_t { + + /** + * Public child_sa_manager_t interface. + */ + child_sa_manager_t public; + + /** + * CHILD_SAs by inbound SPI/dst, child_entry_t => child_entry_t + */ + hashtable_t *in; + + /** + * CHILD_SAs by outbound SPI/dst, child_entry_t => child_entry_t + */ + hashtable_t *out; + + /** + * CHILD_SAs by unique ID, child_entry_t => child_entry_t + */ + hashtable_t *ids; + + /** + * Mutex to access any hashtable + */ + mutex_t *mutex; +}; + +/** + * Hashtable entry for a known CHILD_SA + */ +typedef struct { + /** the associated IKE_SA */ + ike_sa_id_t *ike_id; + /** unique CHILD_SA identifier */ + u_int32_t unique_id; + /** inbound SPI */ + u_int32_t spi_in; + /** outbound SPI */ + u_int32_t spi_out; + /** inbound host address */ + host_t *host_in; + /** outbound host address and port */ + host_t *host_out; + /** IPsec protocol, AH|ESP */ + protocol_id_t proto; +} child_entry_t; + +/** + * Destroy a CHILD_SA entry + */ +static void child_entry_destroy(child_entry_t *entry) +{ + entry->ike_id->destroy(entry->ike_id); + entry->host_in->destroy(entry->host_in); + entry->host_out->destroy(entry->host_out); + free(entry); +} + +/** + * Hashtable hash function for inbound SAs + */ +static u_int hash_in(child_entry_t *entry) +{ + return chunk_hash_inc(chunk_from_thing(entry->spi_in), + chunk_hash_inc(entry->host_in->get_address(entry->host_in), + chunk_hash(chunk_from_thing(entry->proto)))); +} + +/** + * Hashtable equals function for inbound SAs + */ +static bool equals_in(child_entry_t *a, child_entry_t *b) +{ + return a->spi_in == b->spi_in && + a->proto == b->proto && + a->host_in->ip_equals(a->host_in, b->host_in); +} + +/** + * Hashtable hash function for outbound SAs + */ +static u_int hash_out(child_entry_t *entry) +{ + return chunk_hash_inc(chunk_from_thing(entry->spi_out), + chunk_hash_inc(entry->host_out->get_address(entry->host_out), + chunk_hash(chunk_from_thing(entry->proto)))); +} + +/** + * Hashtable equals function for outbound SAs + */ +static bool equals_out(child_entry_t *a, child_entry_t *b) +{ + return a->spi_out == b->spi_out && + a->proto == b->proto && + a->host_out->ip_equals(a->host_out, b->host_out); +} + +/** + * Hashtable hash function for SAs by unique ID + */ +static u_int hash_id(child_entry_t *entry) +{ + return chunk_hash(chunk_from_thing(entry->unique_id)); +} + +/** + * Hashtable equals function for SAs by unique ID + */ +static bool equals_id(child_entry_t *a, child_entry_t *b) +{ + return a->unique_id == b->unique_id; +} + +METHOD(child_sa_manager_t, add, void, + private_child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa) +{ + child_entry_t *entry; + host_t *in, *out; + ike_sa_id_t *id; + + id = ike_sa->get_id(ike_sa); + in = ike_sa->get_my_host(ike_sa); + out = ike_sa->get_other_host(ike_sa); + + INIT(entry, + .ike_id = id->clone(id), + .unique_id = child_sa->get_unique_id(child_sa), + .proto = child_sa->get_protocol(child_sa), + .spi_in = child_sa->get_spi(child_sa, TRUE), + .spi_out = child_sa->get_spi(child_sa, FALSE), + .host_in = in->clone(in), + .host_out = out->clone(out), + ); + + this->mutex->lock(this->mutex); + if (!this->in->get(this->in, entry) && + !this->out->get(this->out, entry)) + { + this->in->put(this->in, entry, entry); + this->out->put(this->out, entry, entry); + entry = this->ids->put(this->ids, entry, entry); + } + this->mutex->unlock(this->mutex); + + if (entry) + { + child_entry_destroy(entry); + } +} + +METHOD(child_sa_manager_t, remove_, void, + private_child_sa_manager_t *this, child_sa_t *child_sa) +{ + child_entry_t *entry, key = { + .unique_id = child_sa->get_unique_id(child_sa), + }; + + this->mutex->lock(this->mutex); + entry = this->ids->remove(this->ids, &key); + if (entry) + { + this->in->remove(this->in, entry); + this->out->remove(this->out, entry); + } + this->mutex->unlock(this->mutex); + + if (entry) + { + child_entry_destroy(entry); + } +} + +/** + * Check out an IKE_SA for a given CHILD_SA + */ +static ike_sa_t *checkout_ikesa(private_child_sa_manager_t *this, + ike_sa_id_t *id, u_int32_t unique_id, child_sa_t **child_sa) +{ + enumerator_t *enumerator; + child_sa_t *current; + ike_sa_t *ike_sa; + bool found = FALSE; + + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id); + id->destroy(id); + if (ike_sa) + { + enumerator = ike_sa->create_child_sa_enumerator(ike_sa); + while (enumerator->enumerate(enumerator, ¤t)) + { + found = current->get_unique_id(current) == unique_id; + if (found) + { + if (child_sa) + { + *child_sa = current; + } + break; + } + } + enumerator->destroy(enumerator); + + if (found) + { + return ike_sa; + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + return NULL; +} + +METHOD(child_sa_manager_t, checkout_by_id, ike_sa_t*, + private_child_sa_manager_t *this, u_int32_t unique_id, + child_sa_t **child_sa) +{ + ike_sa_id_t *id; + child_entry_t *entry, key = { + .unique_id = unique_id, + }; + + this->mutex->lock(this->mutex); + entry = this->ids->get(this->ids, &key); + if (entry) + { + id = entry->ike_id->clone(entry->ike_id); + } + this->mutex->unlock(this->mutex); + + if (entry) + { + return checkout_ikesa(this, id, unique_id, child_sa); + } + return NULL; +} + +METHOD(child_sa_manager_t, checkout, ike_sa_t*, + private_child_sa_manager_t *this, protocol_id_t protocol, u_int32_t spi, + host_t *dst, child_sa_t **child_sa) +{ + ike_sa_id_t *id; + u_int32_t unique_id; + child_entry_t *entry, key = { + .spi_in = spi, + .spi_out = spi, + .host_in = dst, + .host_out = dst, + .proto = protocol, + }; + + this->mutex->lock(this->mutex); + entry = this->in->get(this->in, &key); + if (!entry) + { + entry = this->out->get(this->out, &key); + } + if (entry) + { + unique_id = entry->unique_id; + id = entry->ike_id->clone(entry->ike_id); + } + this->mutex->unlock(this->mutex); + + if (entry) + { + return checkout_ikesa(this, id, unique_id, child_sa); + } + return NULL; +} + +METHOD(child_sa_manager_t, destroy, void, + private_child_sa_manager_t *this) +{ + this->in->destroy(this->in); + this->out->destroy(this->out); + this->ids->destroy(this->ids); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +child_sa_manager_t *child_sa_manager_create() +{ + private_child_sa_manager_t *this; + + INIT(this, + .public = { + .add = _add, + .remove = _remove_, + .checkout = _checkout, + .checkout_by_id = _checkout_by_id, + .destroy = _destroy, + }, + .in = hashtable_create((hashtable_hash_t)hash_in, + (hashtable_equals_t)equals_in, 8), + .out = hashtable_create((hashtable_hash_t)hash_out, + (hashtable_equals_t)equals_out, 8), + .ids = hashtable_create((hashtable_hash_t)hash_id, + (hashtable_equals_t)equals_id, 8), + .mutex = mutex_create(MUTEX_TYPE_DEFAULT), + ); + + return &this->public; +} diff --git a/src/libcharon/sa/child_sa_manager.h b/src/libcharon/sa/child_sa_manager.h new file mode 100644 index 000000000..4d57528e8 --- /dev/null +++ b/src/libcharon/sa/child_sa_manager.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 child_sa_manager child_sa_manager + * @{ @ingroup sa + */ + +#ifndef CHILD_SA_MANAGER_H_ +#define CHILD_SA_MANAGER_H_ + +#include <sa/ike_sa.h> +#include <sa/child_sa.h> + +typedef struct child_sa_manager_t child_sa_manager_t; + +/** + * Handle CHILD_SA to IKE_SA relations + */ +struct child_sa_manager_t { + + /** + * Register a CHILD_SA/IKE_SA relation. + * + * @param child_sa CHILD_SA to register + * @param ike_sa IKE_SA owning the CHILD_SA + */ + void (*add)(child_sa_manager_t *this, child_sa_t *child_sa, ike_sa_t *ike_sa); + + /** + * Unregister a CHILD_SA/IKE_SA relation. + * + * @param child_sa CHILD_SA to unregister + */ + void (*remove)(child_sa_manager_t *this, child_sa_t *child_sa); + + /** + * Find a CHILD_SA and check out the associated IKE_SA by SPI. + * + * On success, the returned IKE_SA must be checked in after use to + * the IKE_SA manager. + * + * @param protocol IPsec protocol, AH|ESP + * @param spi SPI of CHILD_SA to check out + * @param dst SA destination host related to SPI + * @param child_sa returns CHILD_SA managed by IKE_SA + * @return IKE_SA, NULL if not found + */ + ike_sa_t *(*checkout)(child_sa_manager_t *this, + protocol_id_t protocol, u_int32_t spi, host_t *dst, + child_sa_t **child_sa); + + /** + * Find a CHILD_SA and check out the associated IKE_SA by unique_id. + * + * On success, the returned IKE_SA must be checked in after use to + * the IKE_SA manager. + * + * @param unique_id unique ID of CHILD_SA to check out + * @param child_sa returns CHILD_SA managed by IKE_SA + * @return IKE_SA, NULL if not found + */ + ike_sa_t *(*checkout_by_id)(child_sa_manager_t *this, u_int32_t unique_id, + child_sa_t **child_sa); + + /** + * Destroy a child_sa_manager_t. + */ + void (*destroy)(child_sa_manager_t *this); +}; + +/** + * Create a child_sa_manager instance. + */ +child_sa_manager_t *child_sa_manager_create(); + +#endif /** CHILD_SA_MANAGER_H_ @}*/ diff --git a/src/libcharon/sa/eap/eap_method.h b/src/libcharon/sa/eap/eap_method.h index 6242a5a6e..689c0f990 100644 --- a/src/libcharon/sa/eap/eap_method.h +++ b/src/libcharon/sa/eap/eap_method.h @@ -137,6 +137,18 @@ struct eap_method_t { void (*set_identifier) (eap_method_t *this, u_int8_t identifier); /** + * Get authentication details performed by this EAP method. + * + * After EAP completion, the auth data contains additional information + * of the authentication process, used certificates etc. + * This method is optional to implement, but if it is, it must return + * a valid auth_cfg. + * + * @return auth method, internal data + */ + auth_cfg_t* (*get_auth)(eap_method_t *this); + + /** * Destroys a eap_method_t object. */ void (*destroy) (eap_method_t *this); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index d92b9df8e..3aafa4c13 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -932,6 +932,7 @@ METHOD(ike_sa_t, update_hosts, void, /* update our address in any case */ if (force && !me->equals(me, this->my_host)) { + charon->bus->ike_update(charon->bus, &this->public, TRUE, me); set_my_host(this, me->clone(me)); update = TRUE; } @@ -945,6 +946,7 @@ METHOD(ike_sa_t, update_hosts, void, (!has_condition(this, COND_NAT_HERE) || !has_condition(this, COND_ORIGINAL_INITIATOR))) { + charon->bus->ike_update(charon->bus, &this->public, FALSE, other); set_other_host(this, other->clone(other)); update = TRUE; } @@ -964,6 +966,10 @@ METHOD(ike_sa_t, update_hosts, void, enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, &child_sa)) { + charon->child_sa_manager->remove(charon->child_sa_manager, child_sa); + charon->child_sa_manager->add(charon->child_sa_manager, + child_sa, &this->public); + if (child_sa->update(child_sa, this->my_host, this->other_host, vips, has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED) { @@ -971,6 +977,7 @@ METHOD(ike_sa_t, update_hosts, void, child_sa->get_protocol(child_sa), child_sa->get_spi(child_sa, TRUE)); } + } enumerator->destroy(enumerator); @@ -1444,6 +1451,8 @@ METHOD(ike_sa_t, add_child_sa, void, private_ike_sa_t *this, child_sa_t *child_sa) { array_insert_create(&this->child_sas, ARRAY_TAIL, child_sa); + charon->child_sa_manager->add(charon->child_sa_manager, + child_sa, &this->public); } METHOD(ike_sa_t, get_child_sa, child_sa_t*, @@ -1471,16 +1480,58 @@ METHOD(ike_sa_t, get_child_count, int, return array_count(this->child_sas); } +/** + * Private data of a create_child_sa_enumerator() + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner array enumerator */ + enumerator_t *inner; + /** current item */ + child_sa_t *current; +} child_enumerator_t; + +METHOD(enumerator_t, child_enumerate, bool, + child_enumerator_t *this, child_sa_t **child_sa) +{ + if (this->inner->enumerate(this->inner, &this->current)) + { + *child_sa = this->current; + return TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, child_enumerator_destroy, void, + child_enumerator_t *this) +{ + this->inner->destroy(this->inner); + free(this); +} + METHOD(ike_sa_t, create_child_sa_enumerator, enumerator_t*, private_ike_sa_t *this) { - return array_create_enumerator(this->child_sas); + child_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)_child_enumerate, + .destroy = _child_enumerator_destroy, + }, + .inner = array_create_enumerator(this->child_sas), + ); + return &enumerator->public; } METHOD(ike_sa_t, remove_child_sa, void, private_ike_sa_t *this, enumerator_t *enumerator) { - array_remove_at(this->child_sas, enumerator); + child_enumerator_t *ce = (child_enumerator_t*)enumerator; + + charon->child_sa_manager->remove(charon->child_sa_manager, ce->current); + array_remove_at(this->child_sas, ce->inner); } METHOD(ike_sa_t, rekey_child_sa, status_t, @@ -1513,13 +1564,13 @@ METHOD(ike_sa_t, destroy_child_sa, status_t, child_sa_t *child_sa; status_t status = NOT_FOUND; - enumerator = array_create_enumerator(this->child_sas); + enumerator = create_child_sa_enumerator(this); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { if (child_sa->get_protocol(child_sa) == protocol && child_sa->get_spi(child_sa, TRUE) == spi) { - array_remove_at(this->child_sas, enumerator); + remove_child_sa(this, enumerator); child_sa->destroy(child_sa); status = SUCCESS; break; @@ -1771,7 +1822,7 @@ METHOD(ike_sa_t, reestablish, status_t, #endif /* ME */ { /* handle existing CHILD_SAs */ - enumerator = array_create_enumerator(this->child_sas); + enumerator = create_child_sa_enumerator(this); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { if (has_condition(this, COND_REAUTHENTICATING)) @@ -1780,7 +1831,7 @@ METHOD(ike_sa_t, reestablish, status_t, { case CHILD_ROUTED: { /* move routed child directly */ - array_remove_at(this->child_sas, enumerator); + remove_child_sa(this, enumerator); new->add_child_sa(new, child_sa); action = ACTION_NONE; break; @@ -2209,6 +2260,12 @@ METHOD(ike_sa_t, inherit_post, void, array_insert_create(&this->other_vips, ARRAY_TAIL, vip); } + /* MOBIKE additional addresses */ + while (array_remove(other->peer_addresses, ARRAY_HEAD, &vip)) + { + array_insert_create(&this->peer_addresses, ARRAY_TAIL, vip); + } + /* authentication information */ enumerator = array_create_enumerator(other->my_auths); while (enumerator->enumerate(enumerator, &cfg)) @@ -2251,7 +2308,8 @@ METHOD(ike_sa_t, inherit_post, void, /* adopt all children */ while (array_remove(other->child_sas, ARRAY_HEAD, &child_sa)) { - array_insert_create(&this->child_sas, ARRAY_TAIL, child_sa); + charon->child_sa_manager->remove(charon->child_sa_manager, child_sa); + add_child_sa(this, child_sa); } /* move pending tasks to the new IKE_SA */ @@ -2296,8 +2354,8 @@ METHOD(ike_sa_t, destroy, void, { if (entry.handler) { - hydra->attributes->release(hydra->attributes, entry.handler, - this->other_id, entry.type, entry.data); + charon->attributes->release(charon->attributes, entry.handler, + &this->public, entry.type, entry.data); } free(entry.data.ptr); } @@ -2305,6 +2363,7 @@ METHOD(ike_sa_t, destroy, void, * routes that the CHILD_SA tries to uninstall. */ while (array_remove(this->child_sas, ARRAY_TAIL, &child_sa)) { + charon->child_sa_manager->remove(charon->child_sa_manager, child_sa); child_sa->destroy(child_sa); } while (array_remove(this->my_vips, ARRAY_TAIL, &vip)) @@ -2321,12 +2380,11 @@ METHOD(ike_sa_t, destroy, void, if (this->peer_cfg) { linked_list_t *pools; - identification_t *id; - id = get_other_eap_id(this); pools = linked_list_create_from_enumerator( this->peer_cfg->create_pool_enumerator(this->peer_cfg)); - hydra->attributes->release_address(hydra->attributes, pools, vip, id); + charon->attributes->release_address(charon->attributes, + pools, vip, &this->public); pools->destroy(pools); } vip->destroy(vip); diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index c72d87367..9dbc805c9 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -131,6 +131,11 @@ enum ike_extension_t { * peer supports proprietary IKEv1 or standardized IKEv2 fragmentation */ EXT_IKE_FRAGMENTATION = (1<<11), + + /** + * Signature Authentication, RFC 7427 + */ + EXT_SIGNATURE_AUTH = (1<<12), }; /** @@ -936,8 +941,9 @@ struct ike_sa_t { /** * Reauthenticate the IKE_SA. * - * Create a completely new IKE_SA with authentication, recreates all children - * within the IKE_SA, closes this IKE_SA. + * Triggers a new IKE_SA that replaces this one. IKEv1 implicitly inherits + * all Quick Modes, while IKEv2 recreates all active and queued CHILD_SAs + * in the new IKE_SA. * * @return DESTROY_ME to destroy the IKE_SA */ diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index bdabc59b5..13fc74ff7 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1184,7 +1184,8 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, DBG2(DBG_MGR, "checkout IKE_SA by message"); - if (id->get_responder_spi(id) == 0) + if (id->get_responder_spi(id) == 0 && + message->get_message_id(message) == 0) { if (message->get_major_version(message) == IKEV2_MAJOR_VERSION) { @@ -1383,54 +1384,35 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, } METHOD(ike_sa_manager_t, checkout_by_id, ike_sa_t*, - private_ike_sa_manager_t *this, u_int32_t id, bool child) + private_ike_sa_manager_t *this, u_int32_t id) { - enumerator_t *enumerator, *children; + enumerator_t *enumerator; entry_t *entry; ike_sa_t *ike_sa = NULL; - child_sa_t *child_sa; u_int segment; - DBG2(DBG_MGR, "checkout IKE_SA by ID"); + DBG2(DBG_MGR, "checkout IKE_SA by ID %u", id); enumerator = create_table_enumerator(this); while (enumerator->enumerate(enumerator, &entry, &segment)) { if (wait_for_entry(this, entry, segment)) { - /* look for a child with such a reqid ... */ - if (child) - { - children = entry->ike_sa->create_child_sa_enumerator(entry->ike_sa); - while (children->enumerate(children, (void**)&child_sa)) - { - if (child_sa->get_reqid(child_sa) == id) - { - ike_sa = entry->ike_sa; - break; - } - } - children->destroy(children); - } - else /* ... or for a IKE_SA with such a unique id */ - { - if (entry->ike_sa->get_unique_id(entry->ike_sa) == id) - { - ike_sa = entry->ike_sa; - } - } - /* got one, return */ - if (ike_sa) + if (entry->ike_sa->get_unique_id(entry->ike_sa) == id) { + ike_sa = entry->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; } } } enumerator->destroy(enumerator); + if (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)); + } charon->bus->set_sa(charon->bus, ike_sa); return ike_sa; } @@ -1746,29 +1728,45 @@ METHOD(ike_sa_manager_t, create_id_enumerator, enumerator_t*, } /** - * Move all CHILD_SAs from old to new + * Move all CHILD_SAs and virtual IPs from old to new */ -static void adopt_children(ike_sa_t *old, ike_sa_t *new) +static void adopt_children_and_vips(ike_sa_t *old, ike_sa_t *new) { enumerator_t *enumerator; child_sa_t *child_sa; + host_t *vip; + int chcount = 0, vipcount = 0; + enumerator = old->create_child_sa_enumerator(old); while (enumerator->enumerate(enumerator, &child_sa)) { old->remove_child_sa(old, enumerator); new->add_child_sa(new, child_sa); + chcount++; } enumerator->destroy(enumerator); -} -/** - * Check if the replaced IKE_SA might get reauthenticated from host - */ -static bool is_ikev1_reauth(ike_sa_t *duplicate, host_t *host) -{ - return duplicate->get_version(duplicate) == IKEV1 && - host->equals(host, duplicate->get_other_host(duplicate)); + enumerator = old->create_virtual_ip_enumerator(old, FALSE); + while (enumerator->enumerate(enumerator, &vip)) + { + new->add_virtual_ip(new, FALSE, vip); + vipcount++; + } + enumerator->destroy(enumerator); + /* this does not release the addresses, which is good, but it does trigger + * an assign_vips(FALSE) event... */ + old->clear_virtual_ips(old, FALSE); + /* ...trigger the analogous event on the new SA */ + charon->bus->set_sa(charon->bus, new); + charon->bus->assign_vips(charon->bus, new, TRUE); + charon->bus->set_sa(charon->bus, old); + + if (chcount || vipcount) + { + DBG1(DBG_IKE, "detected reauth of existing IKE_SA, adopting %d " + "children and %d virtual IPs", chcount, vipcount); + } } /** @@ -1780,13 +1778,20 @@ static status_t enforce_replace(private_ike_sa_manager_t *this, { charon->bus->alert(charon->bus, ALERT_UNIQUE_REPLACE); - if (is_ikev1_reauth(duplicate, host)) + if (host->equals(host, duplicate->get_other_host(duplicate))) { /* looks like a reauthentication attempt */ - adopt_children(duplicate, new); + if (!new->has_condition(new, COND_INIT_CONTACT_SEEN) && + new->get_version(new) == IKEV1) + { + /* IKEv1 implicitly takes over children, IKEv2 recreates them + * explicitly. */ + adopt_children_and_vips(duplicate, new); + } /* For IKEv1 we have to delay the delete for the old IKE_SA. Some * peers need to complete the new SA first, otherwise the quick modes - * might get lost. */ + * might get lost. For IKEv2 we do the same, as we want overlapping + * CHILD_SAs to keep connectivity up. */ lib->scheduler->schedule_job(lib->scheduler, (job_t*) delete_ike_sa_job_create(duplicate->get_id(duplicate), TRUE), 10); return SUCCESS; @@ -1851,7 +1856,9 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool, other, other_host); break; case UNIQUE_KEEP: - if (!is_ikev1_reauth(duplicate, other_host)) + /* potential reauthentication? */ + if (!other_host->equals(other_host, + duplicate->get_other_host(duplicate))) { cancel = TRUE; /* we keep the first IKE_SA and delete all diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h index a68ae7763..f259d8e56 100644 --- a/src/libcharon/sa/ike_sa_manager.h +++ b/src/libcharon/sa/ike_sa_manager.h @@ -129,19 +129,15 @@ struct ike_sa_manager_t { /** * Check out an IKE_SA a unique ID. * - * Every IKE_SA and every CHILD_SA is uniquely identified by an ID. - * These checkout function uses, depending - * on the child parameter, the unique ID of the IKE_SA or the reqid - * of one of a IKE_SAs CHILD_SA. + * Every IKE_SA is uniquely identified by a numerical ID. This checkout + * function uses the unique ID of the IKE_SA to check it out. * * @param id unique ID of the object - * @param child TRUE to use CHILD, FALSE to use IKE_SA * @return * - checked out IKE_SA, if found * - NULL, if not found */ - ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, u_int32_t id, - bool child); + ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this, u_int32_t id); /** * Check out an IKE_SA by the policy/connection name. diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c index aa966cd5f..bb187f07c 100644 --- a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c +++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c @@ -74,7 +74,10 @@ METHOD(authenticator_t, build, status_t, keymat_v1_t *keymat; chunk_t hash, dh; - this->dh->get_my_public_value(this->dh, &dh); + if (!this->dh->get_my_public_value(this->dh, &dh)) + { + return FAILED; + } keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa); if (!keymat->get_hash(keymat, this->initiator, dh, this->dh_value, this->ike_sa->get_id(this->ike_sa), this->sa_payload, @@ -108,7 +111,10 @@ METHOD(authenticator_t, process, status_t, return FAILED; } - this->dh->get_my_public_value(this->dh, &dh); + if (!this->dh->get_my_public_value(this->dh, &dh)) + { + return FAILED; + } keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa); if (!keymat->get_hash(keymat, !this->initiator, this->dh_value, dh, this->ike_sa->get_id(this->ike_sa), this->sa_payload, diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c index bfe5ff449..52228ef2e 100644 --- a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c +++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c @@ -94,7 +94,11 @@ METHOD(authenticator_t, build, status_t, return NOT_FOUND; } - this->dh->get_my_public_value(this->dh, &dh); + if (!this->dh->get_my_public_value(this->dh, &dh)) + { + private->destroy(private); + return FAILED; + } keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa); if (!keymat->get_hash(keymat, this->initiator, dh, this->dh_value, this->ike_sa->get_id(this->ike_sa), this->sa_payload, @@ -152,7 +156,10 @@ METHOD(authenticator_t, process, status_t, } id = this->ike_sa->get_other_id(this->ike_sa); - this->dh->get_my_public_value(this->dh, &dh); + if (!this->dh->get_my_public_value(this->dh, &dh)) + { + return FAILED; + } keymat = (keymat_v1_t*)this->ike_sa->get_keymat(this->ike_sa); if (!keymat->get_hash(keymat, !this->initiator, this->dh_value, dh, this->ike_sa->get_id(this->ike_sa), this->sa_payload, diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c index 619d197bd..f5a91dbeb 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.c +++ b/src/libcharon/sa/ikev1/keymat_v1.c @@ -425,7 +425,7 @@ METHOD(keymat_v1_t, derive_ike_keys, bool, return FALSE; } - if (dh->get_shared_secret(dh, &g_xy) != SUCCESS) + if (!dh->get_shared_secret(dh, &g_xy)) { return FALSE; } @@ -560,7 +560,10 @@ METHOD(keymat_v1_t, derive_ike_keys, bool, return FALSE; } - dh->get_my_public_value(dh, &dh_me); + if (!dh->get_my_public_value(dh, &dh_me)) + { + return FALSE; + } g_xi = this->initiator ? dh_me : dh_other; g_xr = this->initiator ? dh_other : dh_me; @@ -661,7 +664,7 @@ METHOD(keymat_v1_t, derive_child_keys, bool, protocol = proposal->get_protocol(proposal); if (dh) { - if (dh->get_shared_secret(dh, &secret) != SUCCESS) + if (!dh->get_shared_secret(dh, &secret)) { return FALSE; } diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c index d01a831f8..c968b2a9c 100644 --- a/src/libcharon/sa/ikev1/phase1.c +++ b/src/libcharon/sa/ikev1/phase1.c @@ -694,7 +694,13 @@ METHOD(phase1_t, add_nonce_ke, bool, nonce_gen_t *nonceg; chunk_t nonce; - ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, this->dh); + ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, + this->dh); + if (!ke_payload) + { + DBG1(DBG_IKE, "creating KE payload failed"); + return FALSE; + } message->add_payload(message, &ke_payload->payload_interface); nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat); @@ -739,7 +745,11 @@ METHOD(phase1_t, get_nonce_ke, bool, return FALSE; } this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload)); - this->dh->set_other_public_value(this->dh, this->dh_value); + if (!this->dh->set_other_public_value(this->dh, this->dh_value)) + { + DBG1(DBG_IKE, "unable to apply received KE value"); + return FALSE; + } nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE); if (!nonce_payload) diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 0f8e8bc6d..cb22bf606 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -1596,7 +1596,8 @@ static bool is_redundant(private_task_manager_t *this, child_sa_t *child_sa) child_sa->get_lifetime(child_sa, FALSE)) { DBG1(DBG_IKE, "deleting redundant CHILD_SA %s{%d}", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa)); + child_sa->get_name(child_sa), + child_sa->get_unique_id(child_sa)); redundant = TRUE; break; } @@ -1647,6 +1648,8 @@ METHOD(task_manager_t, queue_child_rekey, void, task = quick_mode_create(this->ike_sa, cfg->get_ref(cfg), get_first_ts(child_sa, TRUE), get_first_ts(child_sa, FALSE)); task->use_reqid(task, child_sa->get_reqid(child_sa)); + task->use_marks(task, child_sa->get_mark(child_sa, TRUE).value, + child_sa->get_mark(child_sa, FALSE).value); task->rekey(task, child_sa->get_spi(child_sa, TRUE)); queue_task(this, &task->task); diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c index bea0428c4..a56805afb 100644 --- a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c +++ b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2015 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2011 Martin Willi * Copyright (C) 2011 revosec AG * @@ -74,6 +77,42 @@ METHOD(task_t, process_i, status_t, METHOD(task_t, process_r, status_t, private_isakmp_delete_t *this, message_t *message) { + enumerator_t *payloads; + payload_t *payload; + delete_payload_t *delete_payload; + ike_sa_id_t *id; + u_int64_t spi_i, spi_r; + bool found = FALSE; + + /* some peers send DELETE payloads for other IKE_SAs, e.g. those for expired + * ones after a rekeyeing, make sure the SPIs match */ + id = this->ike_sa->get_id(this->ike_sa); + payloads = message->create_payload_enumerator(message); + while (payloads->enumerate(payloads, &payload)) + { + if (payload->get_type(payload) == PLV1_DELETE) + { + delete_payload = (delete_payload_t*)payload; + if (!delete_payload->get_ike_spi(delete_payload, &spi_i, &spi_r)) + { + continue; + } + if (id->get_initiator_spi(id) == spi_i && + id->get_responder_spi(id) == spi_r) + { + found = TRUE; + break; + } + } + } + payloads->destroy(payloads); + + if (!found) + { + DBG1(DBG_IKE, "received DELETE for different IKE_SA, ignored"); + return SUCCESS; + } + DBG1(DBG_IKE, "received DELETE for IKE_SA %s[%d]", this->ike_sa->get_name(this->ike_sa), this->ike_sa->get_unique_id(this->ike_sa)); diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index 2fb4c6935..3ea4a2a85 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -205,6 +205,43 @@ static status_t send_delete(private_main_mode_t *this) return ALREADY_DONE; } +/** + * Add an INITIAL_CONTACT notify if first contact with peer + */ +static void add_initial_contact(private_main_mode_t *this, message_t *message, + identification_t *idi) +{ + identification_t *idr; + host_t *host; + notify_payload_t *notify; + ike_sa_id_t *ike_sa_id; + u_int64_t spi_i, spi_r; + chunk_t spi; + + idr = this->ph1->get_id(this->ph1, this->peer_cfg, FALSE); + if (idr && !idr->contains_wildcards(idr)) + { + if (this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO && + this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER) + { + host = this->ike_sa->get_other_host(this->ike_sa); + if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager, + idi, idr, host->get_family(host))) + { + notify = notify_payload_create_from_protocol_and_type( + PLV1_NOTIFY, PROTO_IKE, INITIAL_CONTACT_IKEV1); + ike_sa_id = this->ike_sa->get_id(this->ike_sa); + spi_i = ike_sa_id->get_initiator_spi(ike_sa_id); + spi_r = ike_sa_id->get_responder_spi(ike_sa_id); + spi = chunk_cata("cc", chunk_from_thing(spi_i), + chunk_from_thing(spi_r)); + notify->set_spi_data(notify, spi); + message->add_payload(message, (payload_t*)notify); + } + } + } +} + METHOD(task_t, build_i, status_t, private_main_mode_t *this, message_t *message) { @@ -311,6 +348,8 @@ METHOD(task_t, build_i, status_t, return send_notify(this, AUTHENTICATION_FAILED); } + add_initial_contact(this, message, id); + this->state = MM_AUTH; return NEED_MORE; } diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c index 94026b9af..d0994a961 100644 --- a/src/libcharon/sa/ikev1/tasks/mode_config.c +++ b/src/libcharon/sa/ikev1/tasks/mode_config.c @@ -16,7 +16,6 @@ #include "mode_config.h" #include <daemon.h> -#include <hydra.h> #include <encoding/payloads/cp_payload.h> typedef struct private_mode_config_t private_mode_config_t; @@ -136,9 +135,8 @@ static void handle_attribute(private_mode_config_t *this, enumerator->destroy(enumerator); /* and pass it to the handle function */ - handler = hydra->attributes->handle(hydra->attributes, - this->ike_sa->get_other_id(this->ike_sa), handler, - ca->get_type(ca), ca->get_chunk(ca)); + handler = charon->attributes->handle(charon->attributes, + this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca)); this->ike_sa->add_configuration_attribute(this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca)); } @@ -326,9 +324,8 @@ static status_t build_request(private_mode_config_t *this, message_t *message) enumerator->destroy(enumerator); } - enumerator = hydra->attributes->create_initiator_enumerator( - hydra->attributes, - this->ike_sa->get_other_id(this->ike_sa), vips); + enumerator = charon->attributes->create_initiator_enumerator( + charon->attributes, this->ike_sa, vips); while (enumerator->enumerate(enumerator, &handler, &type, &data)) { add_attribute(this, cp, type, data, handler); @@ -353,7 +350,7 @@ static status_t build_set(private_mode_config_t *this, message_t *message) cp_payload_t *cp; peer_cfg_t *config; identification_t *id; - linked_list_t *pools; + linked_list_t *pools, *migrated, *vips; host_t *any4, *any6, *found; char *name; @@ -361,45 +358,62 @@ static status_t build_set(private_mode_config_t *this, message_t *message) id = this->ike_sa->get_other_eap_id(this->ike_sa); config = this->ike_sa->get_peer_cfg(this->ike_sa); - any4 = host_create_any(AF_INET); - any6 = host_create_any(AF_INET6); + /* if we migrated virtual IPs during reauthentication, reassign them */ + migrated = linked_list_create_from_enumerator( + this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, + FALSE)); + vips = migrated->clone_offset(migrated, offsetof(host_t, clone)); + migrated->destroy(migrated); this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE); /* in push mode, we ask each configured pool for an address */ - enumerator = config->create_pool_enumerator(config); - while (enumerator->enumerate(enumerator, &name)) + if (!vips->get_count(vips)) { - pools = linked_list_create_with_items(name, NULL); - /* try IPv4, then IPv6 */ - found = hydra->attributes->acquire_address(hydra->attributes, - pools, id, any4); - if (!found) - { - found = hydra->attributes->acquire_address(hydra->attributes, - pools, id, any6); - } - pools->destroy(pools); - if (found) + any4 = host_create_any(AF_INET); + any6 = host_create_any(AF_INET6); + enumerator = config->create_pool_enumerator(config); + while (enumerator->enumerate(enumerator, &name)) { - DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id); - this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found); - cp->add_attribute(cp, build_vip(found)); - this->vips->insert_last(this->vips, found); + pools = linked_list_create_with_items(name, NULL); + /* try IPv4, then IPv6 */ + found = charon->attributes->acquire_address(charon->attributes, + pools, this->ike_sa, any4); + if (!found) + { + found = charon->attributes->acquire_address(charon->attributes, + pools, this->ike_sa, any6); + } + pools->destroy(pools); + if (found) + { + vips->insert_last(vips, found); + } } + enumerator->destroy(enumerator); + any4->destroy(any4); + any6->destroy(any6); } - enumerator->destroy(enumerator); - any4->destroy(any4); - any6->destroy(any6); + enumerator = vips->create_enumerator(vips); + while (enumerator->enumerate(enumerator, &found)) + { + DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id); + this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found); + cp->add_attribute(cp, build_vip(found)); + this->vips->insert_last(this->vips, found); + vips->remove_at(vips, enumerator); + } + enumerator->destroy(enumerator); + vips->destroy(vips); charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE); /* query registered providers for additional attributes to include */ pools = linked_list_create_from_enumerator( config->create_pool_enumerator(config)); - enumerator = hydra->attributes->create_responder_enumerator( - hydra->attributes, pools, id, this->vips); + enumerator = charon->attributes->create_responder_enumerator( + charon->attributes, pools, this->ike_sa, this->vips); while (enumerator->enumerate(enumerator, &type, &value)) { add_attribute(this, cp, type, value, NULL); @@ -458,6 +472,28 @@ METHOD(task_t, process_r, status_t, } /** + * Assign a migrated virtual IP + */ +static host_t *assign_migrated_vip(linked_list_t *migrated, host_t *requested) +{ + enumerator_t *enumerator; + host_t *found = NULL, *vip; + + enumerator = migrated->create_enumerator(migrated); + while (enumerator->enumerate(enumerator, &vip)) + { + if (vip->ip_equals(vip, requested)) + { + migrated->remove_at(migrated, enumerator); + found = vip; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** * Build CFG_REPLY message after receiving CFG_REQUEST */ static status_t build_reply(private_mode_config_t *this, message_t *message) @@ -468,29 +504,35 @@ static status_t build_reply(private_mode_config_t *this, message_t *message) cp_payload_t *cp; peer_cfg_t *config; identification_t *id; - linked_list_t *vips, *pools; - host_t *requested; + linked_list_t *vips, *pools, *migrated; + host_t *requested, *found; cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY); id = this->ike_sa->get_other_eap_id(this->ike_sa); config = this->ike_sa->get_peer_cfg(this->ike_sa); - vips = linked_list_create(); pools = linked_list_create_from_enumerator( config->create_pool_enumerator(config)); - + /* if we migrated virtual IPs during reauthentication, reassign them */ + vips = linked_list_create_from_enumerator( + this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, + FALSE)); + migrated = vips->clone_offset(vips, offsetof(host_t, clone)); + vips->destroy(vips); this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE); + vips = linked_list_create(); enumerator = this->vips->create_enumerator(this->vips); while (enumerator->enumerate(enumerator, &requested)) { - host_t *found = NULL; - - /* query all pools until we get an address */ DBG1(DBG_IKE, "peer requested virtual IP %H", requested); - found = hydra->attributes->acquire_address(hydra->attributes, - pools, id, requested); + found = assign_migrated_vip(migrated, requested); + if (!found) + { + found = charon->attributes->acquire_address(charon->attributes, + pools, this->ike_sa, requested); + } if (found) { DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id); @@ -509,8 +551,8 @@ static status_t build_reply(private_mode_config_t *this, message_t *message) charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE); /* query registered providers for additional attributes to include */ - enumerator = hydra->attributes->create_responder_enumerator( - hydra->attributes, pools, id, vips); + enumerator = charon->attributes->create_responder_enumerator( + charon->attributes, pools, this->ike_sa, vips); while (enumerator->enumerate(enumerator, &type, &value)) { cp->add_attribute(cp, @@ -518,6 +560,15 @@ static status_t build_reply(private_mode_config_t *this, message_t *message) type, value)); } enumerator->destroy(enumerator); + /* if a client did not re-request all adresses, release them */ + enumerator = migrated->create_enumerator(migrated); + while (enumerator->enumerate(enumerator, &found)) + { + charon->attributes->release_address(charon->attributes, + pools, found, this->ike_sa); + } + enumerator->destroy(enumerator); + migrated->destroy_offset(migrated, offsetof(host_t, destroy)); vips->destroy_offset(vips, offsetof(host_t, destroy)); pools->destroy(pools); diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c index 499081caa..1b95a8b11 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_delete.c +++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c @@ -105,7 +105,7 @@ static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol, this->spi = spi = child_sa->get_spi(child_sa, TRUE); } - rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYING; + rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED; child_sa->set_state(child_sa, CHILD_DELETING); my_ts = linked_list_create_from_enumerator( @@ -116,7 +116,7 @@ static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol, { DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts); } @@ -127,7 +127,7 @@ static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol, DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs " "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, my_ts, other_ts); diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 1133aab65..96edfd8d8 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -156,6 +156,16 @@ struct private_quick_mode_t { u_int32_t reqid; /** + * Explicit inbound mark value to use, if any + */ + u_int mark_in; + + /** + * Explicit inbound mark value to use, if any + */ + u_int mark_out; + + /** * SPI of SA we rekey */ u_int32_t rekey; @@ -196,8 +206,8 @@ static void schedule_inactivity_timeout(private_quick_mode_t *this) close_ike = lib->settings->get_bool(lib->settings, "%s.inactivity_close_ike", FALSE, lib->ns); lib->scheduler->schedule_job(lib->scheduler, (job_t*) - inactivity_job_create(this->child_sa->get_reqid(this->child_sa), - timeout, close_ike), timeout); + inactivity_job_create(this->child_sa->get_unique_id(this->child_sa), + timeout, close_ike), timeout); } } @@ -375,7 +385,7 @@ static bool install(private_quick_mode_t *this) DBG0(DBG_IKE, "CHILD_SA %s{%d} established " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), + this->child_sa->get_unique_id(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); @@ -391,15 +401,14 @@ static bool install(private_quick_mode_t *this) if (old) { charon->bus->child_rekey(charon->bus, old, this->child_sa); + /* rekeyed CHILD_SAs stay installed until they expire */ + old->set_state(old, CHILD_REKEYED); } else { charon->bus->child_updown(charon->bus, this->child_sa, TRUE); } - if (!this->rekey) - { - schedule_inactivity_timeout(this); - } + schedule_inactivity_timeout(this); this->child_sa = NULL; return TRUE; } @@ -456,12 +465,19 @@ static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce, /** * Add KE payload to message */ -static void add_ke(private_quick_mode_t *this, message_t *message) +static bool add_ke(private_quick_mode_t *this, message_t *message) { ke_payload_t *ke_payload; - ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, this->dh); + ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, + this->dh); + if (!ke_payload) + { + DBG1(DBG_IKE, "creating KE payload failed"); + return FALSE; + } message->add_payload(message, &ke_payload->payload_interface); + return TRUE; } /** @@ -477,8 +493,12 @@ static bool get_ke(private_quick_mode_t *this, message_t *message) DBG1(DBG_IKE, "KE payload missing"); return FALSE; } - this->dh->set_other_public_value(this->dh, - ke_payload->get_key_exchange_data(ke_payload)); + if (!this->dh->set_other_public_value(this->dh, + ke_payload->get_key_exchange_data(ke_payload))) + { + DBG1(DBG_IKE, "unable to apply received KE value"); + return FALSE; + } return TRUE; } @@ -788,7 +808,8 @@ METHOD(task_t, build_i, status_t, this->child_sa = child_sa_create( this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), - this->config, this->reqid, this->udp); + this->config, this->reqid, this->udp, + this->mark_in, this->mark_out); if (this->udp && this->mode == MODE_TRANSPORT) { @@ -870,7 +891,10 @@ METHOD(task_t, build_i, status_t, } if (group != MODP_NONE) { - add_ke(this, message); + if (!add_ke(this, message)) + { + return FAILED; + } } if (!this->tsi) { @@ -964,6 +988,7 @@ static void check_for_rekeyed_child(private_quick_mode_t *this) { case CHILD_INSTALLED: case CHILD_REKEYING: + case CHILD_REKEYED: policies = child_sa->create_policy_enumerator(child_sa); if (policies->enumerate(policies, &local, &remote) && local->equals(local, this->tsr) && @@ -972,9 +997,14 @@ static void check_for_rekeyed_child(private_quick_mode_t *this) { this->reqid = child_sa->get_reqid(child_sa); this->rekey = child_sa->get_spi(child_sa, TRUE); + this->mark_in = child_sa->get_mark(child_sa, + TRUE).value; + this->mark_out = child_sa->get_mark(child_sa, + FALSE).value; child_sa->set_state(child_sa, CHILD_REKEYING); DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}", - child_sa->get_name(child_sa), this->reqid); + child_sa->get_name(child_sa), + child_sa->get_unique_id(child_sa)); } policies->destroy(policies); break; @@ -1097,7 +1127,8 @@ METHOD(task_t, process_r, status_t, this->child_sa = child_sa_create( this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), - this->config, this->reqid, this->udp); + this->config, this->reqid, this->udp, + this->mark_in, this->mark_out); tsi = linked_list_create_with_items(this->tsi, NULL); tsr = linked_list_create_with_items(this->tsr, NULL); @@ -1202,7 +1233,10 @@ METHOD(task_t, build_r, status_t, } if (this->dh) { - add_ke(this, message); + if (!add_ke(this, message)) + { + return FAILED; + } } add_ts(this, message); @@ -1307,6 +1341,13 @@ METHOD(quick_mode_t, use_reqid, void, this->reqid = reqid; } +METHOD(quick_mode_t, use_marks, void, + private_quick_mode_t *this, u_int in, u_int out) +{ + this->mark_in = in; + this->mark_out = out; +} + METHOD(quick_mode_t, rekey, void, private_quick_mode_t *this, u_int32_t spi) { @@ -1334,6 +1375,8 @@ METHOD(task_t, migrate, void, this->dh = NULL; this->spi_i = 0; this->spi_r = 0; + this->mark_in = 0; + this->mark_out = 0; if (!this->initiator) { @@ -1372,6 +1415,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config, .destroy = _destroy, }, .use_reqid = _use_reqid, + .use_marks = _use_marks, .rekey = _rekey, }, .ike_sa = ike_sa, diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.h b/src/libcharon/sa/ikev1/tasks/quick_mode.h index 0b80cb836..ee9b64d13 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.h +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.h @@ -45,6 +45,14 @@ struct quick_mode_t { void (*use_reqid)(quick_mode_t *this, u_int32_t reqid); /** + * Use specific mark values, overriding configuration. + * + * @param in inbound mark value + * @param out outbound mark value + */ + void (*use_marks)(quick_mode_t *this, u_int in, u_int out); + + /** * Set the SPI of the old SA, if rekeying. * * @param spi spi of SA to rekey diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c index eed6d1996..ebef31930 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -522,6 +522,13 @@ METHOD(authenticator_t, process_server, status_t, { return FAILED; } + if (this->method->get_auth) + { + auth_cfg_t *auth; + + auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); + auth->merge(auth, this->method->get_auth(this->method), FALSE); + } return NEED_MORE; } diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c index 6fb14bc06..151b49718 100644 --- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2015 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +20,9 @@ #include <daemon.h> #include <encoding/payloads/auth_payload.h> #include <sa/ikev2/keymat_v2.h> +#include <asn1/asn1.h> +#include <asn1/oid.h> +#include <collections/array.h> typedef struct private_pubkey_authenticator_t private_pubkey_authenticator_t; @@ -52,83 +55,303 @@ struct private_pubkey_authenticator_t { * Reserved bytes of ID payload */ char reserved[3]; + + /** + * Whether to store signature schemes on remote auth configs. + */ + bool store_signature_scheme; }; -METHOD(authenticator_t, build, status_t, - private_pubkey_authenticator_t *this, message_t *message) +/** + * Parse authentication data used for Signature Authentication as per RFC 7427 + */ +static bool parse_signature_auth_data(chunk_t *auth_data, key_type_t *key_type, + signature_scheme_t *scheme) { - chunk_t octets = chunk_empty, auth_data; - status_t status = FAILED; - private_key_t *private; - identification_t *id; - auth_cfg_t *auth; - auth_payload_t *auth_payload; - auth_method_t auth_method; + u_int8_t len; + int oid; + + if (!auth_data->len) + { + return FALSE; + } + len = auth_data->ptr[0]; + *auth_data = chunk_skip(*auth_data, 1); + /* we currently don't support schemes that require parameters */ + oid = asn1_parse_algorithmIdentifier(*auth_data, 1, NULL); + *scheme = signature_scheme_from_oid(oid); + if (*scheme == SIGN_UNKNOWN) + { + return FALSE; + } + *key_type = key_type_from_signature_scheme(*scheme); + *auth_data = chunk_skip(*auth_data, len); + return TRUE; +} + +/** + * Build authentication data used for Signature Authentication as per RFC 7427 + */ +static bool build_signature_auth_data(chunk_t *auth_data, + signature_scheme_t scheme) +{ + chunk_t data; + u_int8_t len; + int oid; + + oid = signature_scheme_to_oid(scheme); + if (oid == OID_UNKNOWN) + { + return FALSE; + } + data = asn1_algorithmIdentifier(oid); + len = data.len; + *auth_data = chunk_cat("cmm", chunk_from_thing(len), data, *auth_data); + return TRUE; +} + +/** + * Selects possible signature schemes based on our configuration, the other + * peer's capabilities and the private key + */ +static array_t *select_signature_schemes(keymat_v2_t *keymat, + auth_cfg_t *auth, private_key_t *private) +{ + enumerator_t *enumerator; signature_scheme_t scheme; + uintptr_t config; + auth_rule_t rule; + key_type_t key_type; + bool have_config = FALSE; + array_t *selected; + + selected = array_create(sizeof(signature_scheme_t), 0); + key_type = private->get_type(private); + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &config)) + { + if (rule != AUTH_RULE_SIGNATURE_SCHEME) + { + continue; + } + have_config = TRUE; + if (key_type == key_type_from_signature_scheme(config) && + keymat->hash_algorithm_supported(keymat, + hasher_from_signature_scheme(config))) + { + scheme = config; + array_insert(selected, ARRAY_TAIL, &scheme); + } + } + enumerator->destroy(enumerator); + + if (!have_config) + { + /* if no specific configuration, find schemes appropriate for the key + * and supported by the other peer */ + enumerator = signature_schemes_for_key(key_type, + private->get_keysize(private)); + while (enumerator->enumerate(enumerator, &scheme)) + { + if (keymat->hash_algorithm_supported(keymat, + hasher_from_signature_scheme(scheme))) + { + array_insert(selected, ARRAY_TAIL, &scheme); + } + } + enumerator->destroy(enumerator); + + /* for RSA we tried at least SHA-512, also try other schemes down to + * what we'd use with classic authentication */ + if (key_type == KEY_RSA) + { + signature_scheme_t schemes[] = { + SIGN_RSA_EMSA_PKCS1_SHA384, + SIGN_RSA_EMSA_PKCS1_SHA256, + SIGN_RSA_EMSA_PKCS1_SHA1, + }, contained; + bool found; + int i, j; + + for (i = 0; i < countof(schemes); i++) + { + scheme = schemes[i]; + found = FALSE; + for (j = 0; j < array_count(selected); j++) + { + array_get(selected, j, &contained); + if (scheme == contained) + { + found = TRUE; + break; + } + } + if (!found && keymat->hash_algorithm_supported(keymat, + hasher_from_signature_scheme(scheme))) + { + array_insert(selected, ARRAY_TAIL, &scheme); + } + } + } + } + return selected; +} + +/** + * Create a signature using RFC 7427 signature authentication + */ +static status_t sign_signature_auth(private_pubkey_authenticator_t *this, + auth_cfg_t *auth, private_key_t *private, + identification_t *id, chunk_t *auth_data) +{ + enumerator_t *enumerator; keymat_v2_t *keymat; + signature_scheme_t scheme = SIGN_UNKNOWN, *schemep; + array_t *schemes; + chunk_t octets = chunk_empty; + status_t status = FAILED; - id = this->ike_sa->get_my_id(this->ike_sa); - auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth); - if (private == NULL) + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); + schemes = select_signature_schemes(keymat, auth, private); + if (!array_count(schemes)) { - DBG1(DBG_IKE, "no private key found for '%Y'", id); - return NOT_FOUND; + DBG1(DBG_IKE, "no common hash algorithm found to create signature " + "with %N key", key_type_names, private->get_type(private)); + array_destroy(schemes); + return FAILED; } + if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init, + this->nonce, id, this->reserved, &octets)) + { + enumerator = array_create_enumerator(schemes); + while (enumerator->enumerate(enumerator, &schemep)) + { + scheme = *schemep; + if (private->sign(private, scheme, octets, auth_data) && + build_signature_auth_data(auth_data, scheme)) + { + status = SUCCESS; + break; + } + else + { + DBG2(DBG_IKE, "unable to create %N signature for %N key", + signature_scheme_names, scheme, key_type_names, + private->get_type(private)); + } + } + enumerator->destroy(enumerator); + } + DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id, + signature_scheme_names, scheme, + status == SUCCESS ? "successful" : "failed"); + array_destroy(schemes); + chunk_free(&octets); + return status; +} + +/** + * Create a classic IKEv2 signature + */ +static status_t sign_classic(private_pubkey_authenticator_t *this, + auth_cfg_t *auth, private_key_t *private, + identification_t *id, auth_method_t *auth_method, + chunk_t *auth_data) +{ + signature_scheme_t scheme; + keymat_v2_t *keymat; + chunk_t octets = chunk_empty; + status_t status = FAILED; + switch (private->get_type(private)) { case KEY_RSA: - /* we currently use always SHA1 for signatures, - * TODO: support other hashes depending on configuration/auth */ scheme = SIGN_RSA_EMSA_PKCS1_SHA1; - auth_method = AUTH_RSA; + *auth_method = AUTH_RSA; break; case KEY_ECDSA: - /* we try to deduct the signature scheme from the keysize */ + /* deduct the signature scheme from the keysize */ switch (private->get_keysize(private)) { case 256: scheme = SIGN_ECDSA_256; - auth_method = AUTH_ECDSA_256; + *auth_method = AUTH_ECDSA_256; break; case 384: scheme = SIGN_ECDSA_384; - auth_method = AUTH_ECDSA_384; + *auth_method = AUTH_ECDSA_384; break; case 521: scheme = SIGN_ECDSA_521; - auth_method = AUTH_ECDSA_521; + *auth_method = AUTH_ECDSA_521; break; default: DBG1(DBG_IKE, "%d bit ECDSA private key size not supported", - private->get_keysize(private)); - return status; + private->get_keysize(private)); + return FAILED; } break; default: DBG1(DBG_IKE, "private key of type %N not supported", - key_type_names, private->get_type(private)); - return status; + key_type_names, private->get_type(private)); + return FAILED; } + keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init, this->nonce, id, this->reserved, &octets) && - private->sign(private, scheme, octets, &auth_data)) + private->sign(private, scheme, octets, auth_data)) { - auth_payload = auth_payload_create(); - auth_payload->set_auth_method(auth_payload, auth_method); - auth_payload->set_data(auth_payload, auth_data); - chunk_free(&auth_data); - message->add_payload(message, (payload_t*)auth_payload); status = SUCCESS; } DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id, - auth_method_names, auth_method, - (status == SUCCESS)? "successful":"failed"); + auth_method_names, *auth_method, + status == SUCCESS ? "successful" : "failed"); chunk_free(&octets); + return status; +} + +METHOD(authenticator_t, build, status_t, + private_pubkey_authenticator_t *this, message_t *message) +{ + private_key_t *private; + identification_t *id; + auth_cfg_t *auth; + chunk_t auth_data; + status_t status; + auth_payload_t *auth_payload; + auth_method_t auth_method; + + id = this->ike_sa->get_my_id(this->ike_sa); + auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); + private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth); + if (!private) + { + DBG1(DBG_IKE, "no private key found for '%Y'", id); + return NOT_FOUND; + } + + if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH)) + { + auth_method = AUTH_DS; + status = sign_signature_auth(this, auth, private, id, &auth_data); + } + else + { + status = sign_classic(this, auth, private, id, &auth_method, + &auth_data); + } private->destroy(private); + if (status == SUCCESS) + { + auth_payload = auth_payload_create(); + auth_payload->set_auth_method(auth_payload, auth_method); + auth_payload->set_data(auth_payload, auth_data); + chunk_free(&auth_data); + message->add_payload(message, (payload_t*)auth_payload); + } return status; } @@ -153,11 +376,10 @@ METHOD(authenticator_t, process, status_t, return FAILED; } auth_method = auth_payload->get_auth_method(auth_payload); + auth_data = auth_payload->get_data(auth_payload); switch (auth_method) { case AUTH_RSA: - /* We currently accept SHA1 signatures only - * TODO: allow other hash algorithms and note it in "auth" */ key_type = KEY_RSA; scheme = SIGN_RSA_EMSA_PKCS1_SHA1; break; @@ -170,10 +392,15 @@ METHOD(authenticator_t, process, status_t, case AUTH_ECDSA_521: scheme = SIGN_ECDSA_521; break; + case AUTH_DS: + if (parse_signature_auth_data(&auth_data, &key_type, &scheme)) + { + break; + } + /* fall-through */ default: return INVALID_ARG; } - auth_data = auth_payload->get_data(auth_payload); id = this->ike_sa->get_other_id(this->ike_sa); keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa); if (!keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init, @@ -188,11 +415,16 @@ METHOD(authenticator_t, process, status_t, { if (public->verify(public, scheme, octets, auth_data)) { - DBG1(DBG_IKE, "authentication of '%Y' with %N successful", - id, auth_method_names, auth_method); + DBG1(DBG_IKE, "authentication of '%Y' with %N successful", id, + auth_method == AUTH_DS ? signature_scheme_names : auth_method_names, + auth_method == AUTH_DS ? scheme : auth_method); status = SUCCESS; auth->merge(auth, current_auth, FALSE); auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + if (this->store_signature_scheme) + { + auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, (uintptr_t)scheme); + } break; } else @@ -265,6 +497,8 @@ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa, .ike_sa = ike_sa, .ike_sa_init = received_init, .nonce = sent_nonce, + .store_signature_scheme = lib->settings->get_bool(lib->settings, + "%s.signature_authentication_constraints", TRUE, lib->ns), ); memcpy(this->reserved, reserved, sizeof(this->reserved)); diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c index 88ad14faf..f70f5cfed 100644 --- a/src/libcharon/sa/ikev2/keymat_v2.c +++ b/src/libcharon/sa/ikev2/keymat_v2.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2015 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -17,6 +18,7 @@ #include <daemon.h> #include <crypto/prf_plus.h> +#include <crypto/hashers/hash_algorithm_set.h> typedef struct private_keymat_v2_t private_keymat_v2_t; @@ -69,6 +71,11 @@ struct private_keymat_v2_t { * Key to verify incoming authentication data (SKp) */ chunk_t skp_verify; + + /** + * Set of hash algorithms supported by peer for signature authentication + */ + hash_algorithm_set_t *hash_algorithms; }; METHOD(keymat_t, get_version, ike_version_t, @@ -293,7 +300,7 @@ METHOD(keymat_v2_t, derive_ike_keys, bool, spi_i = chunk_alloca(sizeof(u_int64_t)); spi_r = chunk_alloca(sizeof(u_int64_t)); - if (dh->get_shared_secret(dh, &secret) != SUCCESS) + if (!dh->get_shared_secret(dh, &secret)) { return FALSE; } @@ -547,7 +554,7 @@ METHOD(keymat_v2_t, derive_child_keys, bool, if (dh) { - if (dh->get_shared_secret(dh, &secret) != SUCCESS) + if (!dh->get_shared_secret(dh, &secret)) { return FALSE; } @@ -676,6 +683,26 @@ METHOD(keymat_v2_t, get_psk_sig, bool, return TRUE; } +METHOD(keymat_v2_t, hash_algorithm_supported, bool, + private_keymat_v2_t *this, hash_algorithm_t hash) +{ + if (!this->hash_algorithms) + { + return FALSE; + } + return this->hash_algorithms->contains(this->hash_algorithms, hash); +} + +METHOD(keymat_v2_t, add_hash_algorithm, void, + private_keymat_v2_t *this, hash_algorithm_t hash) +{ + if (!this->hash_algorithms) + { + this->hash_algorithms = hash_algorithm_set_create(); + } + this->hash_algorithms->add(this->hash_algorithms, hash); +} + METHOD(keymat_t, destroy, void, private_keymat_v2_t *this) { @@ -685,6 +712,7 @@ METHOD(keymat_t, destroy, void, chunk_clear(&this->skd); chunk_clear(&this->skp_verify); chunk_clear(&this->skp_build); + DESTROY_IF(this->hash_algorithms); free(this); } @@ -709,6 +737,9 @@ keymat_v2_t *keymat_v2_create(bool initiator) .get_skd = _get_skd, .get_auth_octets = _get_auth_octets, .get_psk_sig = _get_psk_sig, + .add_hash_algorithm = _add_hash_algorithm, + .hash_algorithm_supported = _hash_algorithm_supported, + }, .initiator = initiator, .prf_alg = PRF_UNDEFINED, diff --git a/src/libcharon/sa/ikev2/keymat_v2.h b/src/libcharon/sa/ikev2/keymat_v2.h index 04432f05b..927b62b03 100644 --- a/src/libcharon/sa/ikev2/keymat_v2.h +++ b/src/libcharon/sa/ikev2/keymat_v2.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Tobias Brunner + * Copyright (C) 2011-2015 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -124,6 +124,22 @@ struct keymat_v2_t { bool (*get_psk_sig)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id, char reserved[3], chunk_t *sig); + + /** + * Add a hash algorithm supported by the peer for signature authentication. + * + * @param hash hash algorithm + */ + void (*add_hash_algorithm)(keymat_v2_t *this, hash_algorithm_t hash); + + /** + * Check if a given hash algorithm is supported by the peer for signature + * authentication. + * + * @param hash hash algorithm + * @return TRUE if supported, FALSE otherwise + */ + bool (*hash_algorithm_supported)(keymat_v2_t *this, hash_algorithm_t hash); }; /** diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index eb7df3516..298167703 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -29,6 +29,7 @@ #include <sa/ikev2/tasks/ike_cert_post.h> #include <sa/ikev2/tasks/ike_rekey.h> #include <sa/ikev2/tasks/ike_reauth.h> +#include <sa/ikev2/tasks/ike_reauth_complete.h> #include <sa/ikev2/tasks/ike_delete.h> #include <sa/ikev2/tasks/ike_config.h> #include <sa/ikev2/tasks/ike_dpd.h> @@ -171,6 +172,11 @@ struct private_task_manager_t { * Base to calculate retransmission timeout */ double retransmit_base; + + /** + * Use make-before-break instead of break-before-make reauth? + */ + bool make_before_break; }; /** @@ -510,6 +516,11 @@ METHOD(task_manager_t, initiate, status_t, break; } #endif /* ME */ + if (activate_task(this, TASK_IKE_REAUTH_COMPLETE)) + { + exchange = INFORMATIONAL; + break; + } case IKE_REKEYING: if (activate_task(this, TASK_IKE_DELETE)) { @@ -604,6 +615,11 @@ METHOD(task_manager_t, initiate, status_t, /* update exchange type if a task changed it */ this->initiating.type = message->get_exchange_type(message); + if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED) + { + message->destroy(message); + return SUCCESS; + } if (!generate_message(this, message, &this->initiating.packets)) { @@ -1170,7 +1186,7 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg) { unknown = (unknown_payload_t*)payload; type = payload->get_type(payload); - if (!payload_is_known(type) && + if (!payload_is_known(type, msg->get_major_version(msg)) && unknown->is_critical(unknown)) { DBG1(DBG_ENC, "payload type %N is not supported, " @@ -1288,17 +1304,16 @@ METHOD(task_manager_t, process_message, status_t, { if (mid == this->responding.mid) { - /* reject initial messages once established */ - if (msg->get_exchange_type(msg) == IKE_SA_INIT || - msg->get_exchange_type(msg) == IKE_AUTH) + /* reject initial messages if not received in specific states */ + if ((msg->get_exchange_type(msg) == IKE_SA_INIT && + this->ike_sa->get_state(this->ike_sa) != IKE_CREATED) || + (msg->get_exchange_type(msg) == IKE_AUTH && + this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)) { - if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && - this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) - { - DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", - exchange_type_names, msg->get_exchange_type(msg)); - return FAILED; - } + DBG1(DBG_IKE, "ignoring %N in IKE_SA state %N", + exchange_type_names, msg->get_exchange_type(msg), + ike_sa_state_names, this->ike_sa->get_state(this->ike_sa)); + return FAILED; } if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE)) { /* with MOBIKE, we do no implicit updates */ @@ -1339,10 +1354,6 @@ METHOD(task_manager_t, process_message, status_t, { DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", mid, this->responding.mid); - if (msg->get_exchange_type(msg) == IKE_SA_INIT) - { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ - return DESTROY_ME; - } } } else @@ -1505,9 +1516,79 @@ METHOD(task_manager_t, queue_ike_rekey, void, queue_task(this, (task_t*)ike_rekey_create(this->ike_sa, TRUE)); } +/** + * Start reauthentication using make-before-break + */ +static void trigger_mbb_reauth(private_task_manager_t *this) +{ + enumerator_t *enumerator; + child_sa_t *child_sa; + child_cfg_t *cfg; + ike_sa_t *new; + host_t *host; + task_t *task; + + new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager, + this->ike_sa->get_version(this->ike_sa), TRUE); + if (!new) + { /* shouldn't happen */ + return; + } + + new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa)); + host = this->ike_sa->get_other_host(this->ike_sa); + new->set_other_host(new, host->clone(host)); + host = this->ike_sa->get_my_host(this->ike_sa); + new->set_my_host(new, host->clone(host)); + enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE); + while (enumerator->enumerate(enumerator, &host)) + { + new->add_virtual_ip(new, TRUE, host); + } + enumerator->destroy(enumerator); + + enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa); + while (enumerator->enumerate(enumerator, &child_sa)) + { + cfg = child_sa->get_config(child_sa); + new->queue_task(new, &child_create_create(new, cfg->get_ref(cfg), + FALSE, NULL, NULL)->task); + } + enumerator->destroy(enumerator); + + enumerator = array_create_enumerator(this->queued_tasks); + while (enumerator->enumerate(enumerator, &task)) + { + if (task->get_type(task) == TASK_CHILD_CREATE) + { + task->migrate(task, new); + new->queue_task(new, task); + array_remove_at(this->queued_tasks, enumerator); + } + } + enumerator->destroy(enumerator); + + if (new->initiate(new, NULL, 0, NULL, NULL) != DESTROY_ME) + { + new->queue_task(new, (task_t*)ike_reauth_complete_create(new, + this->ike_sa->get_id(this->ike_sa))); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, new); + } + else + { + charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new); + DBG1(DBG_IKE, "reauthenticating IKE_SA failed"); + } + charon->bus->set_sa(charon->bus, this->ike_sa); +} + METHOD(task_manager_t, queue_ike_reauth, void, private_task_manager_t *this) { + if (this->make_before_break) + { + return trigger_mbb_reauth(this); + } queue_task(this, (task_t*)ike_reauth_create(this->ike_sa)); } @@ -1773,6 +1854,8 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa) "%s.retransmit_timeout", RETRANSMIT_TIMEOUT, lib->ns), .retransmit_base = lib->settings->get_double(lib->settings, "%s.retransmit_base", RETRANSMIT_BASE, lib->ns), + .make_before_break = lib->settings->get_bool(lib->settings, + "%s.make_before_break", FALSE, lib->ns), ); return &this->public; diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index a1f01c276..6d9132a68 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -105,6 +105,11 @@ struct private_child_create_t { diffie_hellman_t *dh; /** + * Applying DH public value failed? + */ + bool dh_failed; + + /** * group used for DH exchange */ diffie_hellman_group_t dh_group; @@ -160,6 +165,16 @@ struct private_child_create_t { u_int32_t reqid; /** + * Explicit inbound mark value + */ + u_int mark_in; + + /** + * Explicit outbound mark value + */ + u_int mark_out; + + /** * CHILD_SA which gets established */ child_sa_t *child_sa; @@ -286,7 +301,7 @@ static bool allocate_spi(private_child_create_t *this) */ static void schedule_inactivity_timeout(private_child_create_t *this) { - u_int32_t timeout; + u_int32_t timeout, id; bool close_ike; timeout = this->config->get_inactivity(this->config); @@ -294,9 +309,9 @@ static void schedule_inactivity_timeout(private_child_create_t *this) { close_ike = lib->settings->get_bool(lib->settings, "%s.inactivity_close_ike", FALSE, lib->ns); + id = this->child_sa->get_unique_id(this->child_sa); lib->scheduler->schedule_job(lib->scheduler, (job_t*) - inactivity_job_create(this->child_sa->get_reqid(this->child_sa), - timeout, close_ike), timeout); + inactivity_job_create(id, timeout, close_ike), timeout); } } @@ -683,10 +698,7 @@ static status_t select_and_install(private_child_create_t *this, this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); this->established = TRUE; - if (!this->rekey) - { /* a rekeyed SA uses the same reqid, no need for a new job */ - schedule_inactivity_timeout(this); - } + schedule_inactivity_timeout(this); my_ts = linked_list_create_from_enumerator( this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); @@ -696,7 +708,7 @@ static status_t select_and_install(private_child_create_t *this, DBG0(DBG_IKE, "CHILD_SA %s{%d} established " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), + this->child_sa->get_unique_id(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); @@ -709,7 +721,7 @@ static status_t select_and_install(private_child_create_t *this, /** * build the payloads for the message */ -static void build_payloads(private_child_create_t *this, message_t *message) +static bool build_payloads(private_child_create_t *this, message_t *message) { sa_payload_t *sa_payload; nonce_payload_t *nonce_payload; @@ -741,6 +753,11 @@ static void build_payloads(private_child_create_t *this, message_t *message) { ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE, this->dh); + if (!ke_payload) + { + DBG1(DBG_IKE, "creating KE payload failed"); + return FALSE; + } message->add_payload(message, (payload_t*)ke_payload); } @@ -769,6 +786,7 @@ static void build_payloads(private_child_create_t *this, message_t *message) message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED, chunk_empty); } + return TRUE; } /** @@ -880,7 +898,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) } if (this->dh) { - this->dh->set_other_public_value(this->dh, + this->dh_failed = !this->dh->set_other_public_value(this->dh, ke_payload->get_key_exchange_data(ke_payload)); } break; @@ -996,7 +1014,8 @@ METHOD(task_t, build_i, status_t, this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY), + this->mark_in, this->mark_out); if (!allocate_spi(this)) { @@ -1027,7 +1046,10 @@ METHOD(task_t, build_i, status_t, NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr); } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + return FAILED; + } this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); @@ -1168,12 +1190,19 @@ METHOD(task_t, build_r, status_t, case IKE_SA_INIT: return get_nonce(message, &this->my_nonce); case CREATE_CHILD_SA: - if (generate_nonce(this) != SUCCESS) + if (generate_nonce(this) != SUCCESS ) { message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); return SUCCESS; } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, + chunk_empty); + return SUCCESS; + } no_dh = FALSE; break; case IKE_AUTH: @@ -1241,7 +1270,8 @@ METHOD(task_t, build_r, status_t, this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, - this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY), + this->mark_in, this->mark_out); if (this->ipcomp_received != IPCOMP_NONE) { @@ -1279,7 +1309,12 @@ METHOD(task_t, build_r, status_t, return SUCCESS; } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); + handle_child_sa_failure(this, message); + return SUCCESS; + } if (!this->rekey) { /* invoke the child_up() hook if we are not rekeying */ @@ -1408,6 +1443,7 @@ METHOD(task_t, process_i, status_t, this->dh_group, diffie_hellman_group_names, group); this->retry = TRUE; this->dh_group = group; + this->child_sa->set_state(this->child_sa, CHILD_RETRYING); this->public.task.migrate(&this->public.task, this->ike_sa); enumerator->destroy(enumerator); return NEED_MORE; @@ -1456,6 +1492,13 @@ METHOD(task_t, process_i, status_t, return delete_failed_sa(this); } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + handle_child_sa_failure(this, message); + return delete_failed_sa(this); + } + if (select_and_install(this, no_dh, ike_auth) == SUCCESS) { if (!this->rekey) @@ -1477,6 +1520,13 @@ METHOD(child_create_t, use_reqid, void, this->reqid = reqid; } +METHOD(child_create_t, use_marks, void, + private_child_create_t *this, u_int in, u_int out) +{ + this->mark_in = in; + this->mark_out = out; +} + METHOD(child_create_t, get_child, child_sa_t*, private_child_create_t *this) { @@ -1526,6 +1576,7 @@ METHOD(task_t, migrate, void, DESTROY_IF(this->child_sa); DESTROY_IF(this->proposal); DESTROY_IF(this->dh); + this->dh_failed = FALSE; if (this->proposals) { this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); @@ -1544,6 +1595,8 @@ METHOD(task_t, migrate, void, this->ipcomp_received = IPCOMP_NONE; this->other_cpi = 0; this->reqid = 0; + this->mark_in = 0; + this->mark_out = 0; this->established = FALSE; } @@ -1592,6 +1645,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, .set_config = _set_config, .get_lower_nonce = _get_lower_nonce, .use_reqid = _use_reqid, + .use_marks = _use_marks, .task = { .get_type = _get_type, .migrate = _migrate, diff --git a/src/libcharon/sa/ikev2/tasks/child_create.h b/src/libcharon/sa/ikev2/tasks/child_create.h index d29ba3d98..46d9403ee 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.h +++ b/src/libcharon/sa/ikev2/tasks/child_create.h @@ -52,6 +52,14 @@ struct child_create_t { void (*use_reqid) (child_create_t *this, u_int32_t reqid); /** + * Use specific mark values to override configuration. + * + * @param in inbound mark value + * @param out outbound mark value + */ + void (*use_marks)(child_create_t *this, u_int in, u_int out); + + /** * Get the lower of the two nonces, used for rekey collisions. * * @return lower nonce diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c index 2b1697423..f0b11e291 100644 --- a/src/libcharon/sa/ikev2/tasks/child_delete.c +++ b/src/libcharon/sa/ikev2/tasks/child_delete.c @@ -267,7 +267,7 @@ static void log_children(private_child_delete_t *this) { DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts); } @@ -278,7 +278,7 @@ static void log_children(private_child_delete_t *this) DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i " "(%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", - child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), + child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, my_ts, other_ts); diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index db872827d..c806e19ca 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -96,9 +96,9 @@ static void schedule_delayed_rekey(private_child_rekey_t *this) retry = RETRY_INTERVAL - (random() % RETRY_JITTER); job = (job_t*)rekey_child_sa_job_create( - this->child_sa->get_reqid(this->child_sa), this->child_sa->get_protocol(this->child_sa), - this->child_sa->get_spi(this->child_sa, TRUE)); + this->child_sa->get_spi(this->child_sa, TRUE), + this->ike_sa->get_my_host(this->ike_sa)); DBG1(DBG_IKE, "CHILD_SA rekeying failed, trying again in %d seconds", retry); this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); lib->scheduler->schedule_job(lib->scheduler, job, retry); @@ -184,6 +184,9 @@ METHOD(task_t, build_i, status_t, } reqid = this->child_sa->get_reqid(this->child_sa); this->child_create->use_reqid(this->child_create, reqid); + this->child_create->use_marks(this->child_create, + this->child_sa->get_mark(this->child_sa, TRUE).value, + this->child_sa->get_mark(this->child_sa, FALSE).value); if (this->child_create->task.build(&this->child_create->task, message) != NEED_MORE) @@ -224,6 +227,9 @@ METHOD(task_t, build_r, status_t, /* let the CHILD_CREATE task build the response */ reqid = this->child_sa->get_reqid(this->child_sa); this->child_create->use_reqid(this->child_create, reqid); + this->child_create->use_marks(this->child_create, + this->child_sa->get_mark(this->child_sa, TRUE).value, + this->child_sa->get_mark(this->child_sa, FALSE).value); config = this->child_sa->get_config(this->child_sa); this->child_create->set_config(this->child_create, config->get_ref(config)); this->child_create->task.build(&this->child_create->task, message); diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c index 0dac975e7..ca17494de 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c +++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c @@ -229,12 +229,12 @@ static void process_x509(cert_payload_t *payload, auth_cfg_t *auth, return; } url = strdup(url); - if (first) + if (*first) { /* first URL is for an end entity certificate */ DBG1(DBG_IKE, "received hash-and-url for end entity cert \"%s\"", url); auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url); - first = FALSE; + *first = FALSE; } else { diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c index da06e2a36..646f20c61 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_config.c +++ b/src/libcharon/sa/ikev2/tasks/ike_config.c @@ -17,7 +17,6 @@ #include "ike_config.h" #include <daemon.h> -#include <hydra.h> #include <encoding/payloads/cp_payload.h> typedef struct private_ike_config_t private_ike_config_t; @@ -127,9 +126,8 @@ static void handle_attribute(private_ike_config_t *this, enumerator->destroy(enumerator); /* and pass it to the handle function */ - handler = hydra->attributes->handle(hydra->attributes, - this->ike_sa->get_other_id(this->ike_sa), handler, - ca->get_type(ca), ca->get_chunk(ca)); + handler = charon->attributes->handle(charon->attributes, + this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca)); this->ike_sa->add_configuration_attribute(this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca)); } @@ -274,9 +272,8 @@ METHOD(task_t, build_i, status_t, enumerator->destroy(enumerator); } - enumerator = hydra->attributes->create_initiator_enumerator( - hydra->attributes, - this->ike_sa->get_other_id(this->ike_sa), vips); + enumerator = charon->attributes->create_initiator_enumerator( + charon->attributes, this->ike_sa, vips); while (enumerator->enumerate(enumerator, &handler, &type, &data)) { configuration_attribute_t *ca; @@ -352,8 +349,8 @@ METHOD(task_t, build_r, status_t, /* query all pools until we get an address */ DBG1(DBG_IKE, "peer requested virtual IP %H", requested); - found = hydra->attributes->acquire_address(hydra->attributes, - pools, id, requested); + found = charon->attributes->acquire_address(charon->attributes, + pools, this->ike_sa, requested); if (found) { DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id); @@ -398,8 +395,8 @@ METHOD(task_t, build_r, status_t, } /* query registered providers for additional attributes to include */ - enumerator = hydra->attributes->create_responder_enumerator( - hydra->attributes, pools, id, vips); + enumerator = charon->attributes->create_responder_enumerator( + charon->attributes, pools, this->ike_sa, vips); while (enumerator->enumerate(enumerator, &type, &value)) { if (!cp) diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index 71c5f22fa..0d5700ef2 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2008-2015 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,8 +20,11 @@ #include <string.h> #include <daemon.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> #include <sa/ikev2/keymat_v2.h> #include <crypto/diffie_hellman.h> +#include <crypto/hashers/hash_algorithm_set.h> #include <encoding/payloads/sa_payload.h> #include <encoding/payloads/ke_payload.h> #include <encoding/payloads/nonce_payload.h> @@ -67,6 +70,11 @@ struct private_ike_init_t { diffie_hellman_t *dh; /** + * Applying DH public value failed? + */ + bool dh_failed; + + /** * Keymat derivation (from IKE_SA) */ keymat_v2_t *keymat; @@ -100,12 +108,114 @@ struct private_ike_init_t { * retries done so far after failure (cookie or bad dh group) */ u_int retry; + + /** + * Whether to use Signature Authentication as per RFC 7427 + */ + bool signature_authentication; }; /** + * Notify the peer about the hash algorithms we support or expect, + * as per RFC 7427 + */ +static void send_supported_hash_algorithms(private_ike_init_t *this, + message_t *message) +{ + hash_algorithm_set_t *algos; + enumerator_t *enumerator, *rounds; + bio_writer_t *writer; + hash_algorithm_t hash; + peer_cfg_t *peer; + auth_cfg_t *auth; + auth_rule_t rule; + uintptr_t config; + char *plugin_name; + + algos = hash_algorithm_set_create(); + peer = this->ike_sa->get_peer_cfg(this->ike_sa); + if (peer) + { + rounds = peer->create_auth_cfg_enumerator(peer, FALSE); + while (rounds->enumerate(rounds, &auth)) + { + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &config)) + { + if (rule == AUTH_RULE_SIGNATURE_SCHEME) + { + hash = hasher_from_signature_scheme(config); + if (hasher_algorithm_for_ikev2(hash)) + { + algos->add(algos, hash); + } + } + } + enumerator->destroy(enumerator); + } + rounds->destroy(rounds); + } + + if (!algos->count(algos)) + { + enumerator = lib->crypto->create_hasher_enumerator(lib->crypto); + while (enumerator->enumerate(enumerator, &hash, &plugin_name)) + { + if (hasher_algorithm_for_ikev2(hash)) + { + algos->add(algos, hash); + } + } + enumerator->destroy(enumerator); + } + + if (algos->count(algos)) + { + writer = bio_writer_create(0); + enumerator = algos->create_enumerator(algos); + while (enumerator->enumerate(enumerator, &hash)) + { + writer->write_uint16(writer, hash); + } + enumerator->destroy(enumerator); + message->add_notify(message, FALSE, SIGNATURE_HASH_ALGORITHMS, + writer->get_buf(writer)); + writer->destroy(writer); + } + algos->destroy(algos); +} + +/** + * Store algorithms supported by other peer + */ +static void handle_supported_hash_algorithms(private_ike_init_t *this, + notify_payload_t *notify) +{ + bio_reader_t *reader; + u_int16_t algo; + bool added = FALSE; + + reader = bio_reader_create(notify->get_notification_data(notify)); + while (reader->remaining(reader) >= 2 && reader->read_uint16(reader, &algo)) + { + if (hasher_algorithm_for_ikev2(algo)) + { + this->keymat->add_hash_algorithm(this->keymat, algo); + added = TRUE; + } + } + reader->destroy(reader); + + if (added) + { + this->ike_sa->enable_extension(this->ike_sa, EXT_SIGNATURE_AUTH); + } +} + +/** * build the payloads for the message */ -static void build_payloads(private_ike_init_t *this, message_t *message) +static bool build_payloads(private_ike_init_t *this, message_t *message) { sa_payload_t *sa_payload; ke_payload_t *ke_payload; @@ -149,7 +259,13 @@ static void build_payloads(private_ike_init_t *this, message_t *message) nonce_payload = nonce_payload_create(PLV2_NONCE); nonce_payload->set_nonce(nonce_payload, this->my_nonce); - ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE, this->dh); + ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE, + this->dh); + if (!ke_payload) + { + DBG1(DBG_IKE, "creating KE payload failed"); + return FALSE; + } if (this->old_sa) { /* payload order differs if we are rekeying */ @@ -174,6 +290,17 @@ static void build_payloads(private_ike_init_t *this, message_t *message) chunk_empty); } } + /* submit supported hash algorithms for signature authentication */ + if (!this->old_sa && this->signature_authentication) + { + if (this->initiator || + this->ike_sa->supports_extension(this->ike_sa, + EXT_SIGNATURE_AUTH)) + { + send_supported_hash_algorithms(this, message); + } + } + return TRUE; } /** @@ -183,6 +310,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message) { enumerator_t *enumerator; payload_t *payload; + ke_payload_t *ke_payload = NULL; enumerator = message->create_payload_enumerator(message); while (enumerator->enumerate(enumerator, &payload)) @@ -211,19 +339,9 @@ static void process_payloads(private_ike_init_t *this, message_t *message) } case PLV2_KEY_EXCHANGE: { - ke_payload_t *ke_payload = (ke_payload_t*)payload; + ke_payload = (ke_payload_t*)payload; this->dh_group = ke_payload->get_dh_group_number(ke_payload); - if (!this->initiator) - { - this->dh = this->keymat->keymat.create_dh( - &this->keymat->keymat, this->dh_group); - } - if (this->dh) - { - this->dh->set_other_public_value(this->dh, - ke_payload->get_key_exchange_data(ke_payload)); - } break; } case PLV2_NONCE: @@ -237,17 +355,44 @@ static void process_payloads(private_ike_init_t *this, message_t *message) { notify_payload_t *notify = (notify_payload_t*)payload; - if (notify->get_notify_type(notify) == FRAGMENTATION_SUPPORTED) + switch (notify->get_notify_type(notify)) { - this->ike_sa->enable_extension(this->ike_sa, - EXT_IKE_FRAGMENTATION); + case FRAGMENTATION_SUPPORTED: + this->ike_sa->enable_extension(this->ike_sa, + EXT_IKE_FRAGMENTATION); + break; + case SIGNATURE_HASH_ALGORITHMS: + if (this->signature_authentication) + { + handle_supported_hash_algorithms(this, notify); + } + break; + default: + /* other notifies are handled elsewhere */ + break; } + } default: break; } } enumerator->destroy(enumerator); + + if (ke_payload && this->proposal && + this->proposal->has_dh_group(this->proposal, this->dh_group)) + { + if (!this->initiator) + { + this->dh = this->keymat->keymat.create_dh( + &this->keymat->keymat, this->dh_group); + } + if (this->dh) + { + this->dh_failed = !this->dh->set_other_public_value(this->dh, + ke_payload->get_key_exchange_data(ke_payload)); + } + } } METHOD(task_t, build_i, status_t, @@ -305,7 +450,10 @@ METHOD(task_t, build_i, status_t, message->add_notify(message, FALSE, COOKIE, this->cookie); } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + return FAILED; + } #ifdef ME { @@ -433,13 +581,24 @@ METHOD(task_t, build_r, status_t, return FAILED; } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); + return FAILED; + } + if (!derive_keys(this, this->other_nonce, this->my_nonce)) { DBG1(DBG_IKE, "key derivation failed"); message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); return FAILED; } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); + return FAILED; + } return SUCCESS; } @@ -554,6 +713,12 @@ METHOD(task_t, process_i, status_t, return FAILED; } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + return FAILED; + } + if (!derive_keys(this, this->my_nonce, this->other_nonce)) { DBG1(DBG_IKE, "key derivation failed"); @@ -577,6 +742,7 @@ METHOD(task_t, migrate, void, this->ike_sa = ike_sa; this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); this->proposal = NULL; + this->dh_failed = FALSE; if (this->dh && this->dh->get_dh_group(this->dh) != this->dh_group) { /* reset DH value only if group changed (INVALID_KE_PAYLOAD) */ this->dh->destroy(this->dh); @@ -631,6 +797,8 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa) .dh_group = MODP_NONE, .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa), .old_sa = old_sa, + .signature_authentication = lib->settings->get_bool(lib->settings, + "%s.signature_authentication", TRUE, lib->ns), ); if (initiator) diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c index d91fa5862..6295d7960 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c +++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c @@ -256,6 +256,7 @@ static void update_children(private_ike_mobike_t *this) enumerator_t *enumerator; child_sa_t *child_sa; linked_list_t *vips; + status_t status; host_t *host; vips = linked_list_create(); @@ -270,15 +271,25 @@ static void update_children(private_ike_mobike_t *this) enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { - if (child_sa->update(child_sa, - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), vips, - this->ike_sa->has_condition(this->ike_sa, - COND_NAT_ANY)) == NOT_SUPPORTED) + status = child_sa->update(child_sa, + this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa), vips, + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); + switch (status) { - this->ike_sa->rekey_child_sa(this->ike_sa, - child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + case NOT_SUPPORTED: + this->ike_sa->rekey_child_sa(this->ike_sa, + child_sa->get_protocol(child_sa), + child_sa->get_spi(child_sa, TRUE)); + break; + case SUCCESS: + charon->child_sa_manager->remove(charon->child_sa_manager, + child_sa); + charon->child_sa_manager->add(charon->child_sa_manager, + child_sa, this->ike_sa); + break; + default: + break; } } enumerator->destroy(enumerator); diff --git a/src/libcharon/sa/ikev2/tasks/ike_reauth.h b/src/libcharon/sa/ikev2/tasks/ike_reauth.h index 781b463a7..e2e48f0d4 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_reauth.h +++ b/src/libcharon/sa/ikev2/tasks/ike_reauth.h @@ -29,6 +29,8 @@ typedef struct ike_reauth_t ike_reauth_t; /** * Task of type ike_reauth, reestablishes an IKE_SA. + * + * This task implements break-before-make reauthentication. */ struct ike_reauth_t { diff --git a/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.c b/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.c new file mode 100644 index 000000000..a01489c03 --- /dev/null +++ b/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 "ike_reauth_complete.h" + +#include <daemon.h> +#include <processing/jobs/delete_ike_sa_job.h> + + +typedef struct private_ike_reauth_complete_t private_ike_reauth_complete_t; + +/** + * Private members of a ike_reauth_complete_t task. + */ +struct private_ike_reauth_complete_t { + + /** + * Public methods and task_t interface. + */ + ike_reauth_complete_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Reauthenticated IKE_SA identifier + */ + ike_sa_id_t *id; +}; + +METHOD(task_t, build_i, status_t, + private_ike_reauth_complete_t *this, message_t *message) +{ + message->set_exchange_type(message, EXCHANGE_TYPE_UNDEFINED); + lib->processor->queue_job(lib->processor, + (job_t*)delete_ike_sa_job_create(this->id, TRUE)); + return SUCCESS; +} + +METHOD(task_t, process_i, status_t, + private_ike_reauth_complete_t *this, message_t *message) +{ + return DESTROY_ME; +} + +METHOD(task_t, get_type, task_type_t, + private_ike_reauth_complete_t *this) +{ + return TASK_IKE_REAUTH_COMPLETE; +} + +METHOD(task_t, migrate, void, + private_ike_reauth_complete_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; +} + +METHOD(task_t, destroy, void, + private_ike_reauth_complete_t *this) +{ + this->id->destroy(this->id); + free(this); +} + +/* + * Described in header. + */ +ike_reauth_complete_t *ike_reauth_complete_create(ike_sa_t *ike_sa, + ike_sa_id_t *id) +{ + private_ike_reauth_complete_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .migrate = _migrate, + .build = _build_i, + .process = _process_i, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + .id = id->clone(id), + ); + + return &this->public; +} diff --git a/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.h b/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.h new file mode 100644 index 000000000..cc3d3b713 --- /dev/null +++ b/src/libcharon/sa/ikev2/tasks/ike_reauth_complete.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 ike_reauth_complete ike_reauth_complete + * @{ @ingroup tasks_v2 + */ + +#ifndef IKE_REAUTH_COMPLETE_H_ +#define IKE_REAUTH_COMPLETE_H_ + +typedef struct ike_reauth_complete_t ike_reauth_complete_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/task.h> + +/** + * Task of type IKE_REAUTH_COMPLETE, removes reauthenticated SA after reauth. + * + * This task completes make-before-break reauthentication by deleting the + * old, reauthenticated IKE_SA after the new one established. + */ +struct ike_reauth_complete_t { + + /** + * Implements the task_t interface + */ + task_t task; +}; + +/** + * Create a new ike_reauth_complete task. + * + * This task is initiator only. + * + * @param ike_sa IKE_SA this task works for + * @param id old, reauthenticated IKE_SA + * @return ike_reauth_complete task to handle by the task_manager + */ +ike_reauth_complete_t *ike_reauth_complete_create(ike_sa_t *ike_sa, + ike_sa_id_t *id); + +#endif /** IKE_REAUTH_COMPLETE_H_ @}*/ diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c index 444ac6ade..1855517ce 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c @@ -22,6 +22,7 @@ #include <sa/ikev2/tasks/ike_delete.h> #include <processing/jobs/delete_ike_sa_job.h> #include <processing/jobs/rekey_ike_sa_job.h> +#include <processing/jobs/initiate_tasks_job.h> typedef struct private_ike_rekey_t private_ike_rekey_t; @@ -68,12 +69,33 @@ struct private_ike_rekey_t { }; /** + * Check if an IKE_SA has any queued tasks, return initiation job + */ +static job_t* check_queued_tasks(ike_sa_t *ike_sa) +{ + enumerator_t *enumerator; + task_t *task; + job_t *job = NULL; + + enumerator = ike_sa->create_task_enumerator(ike_sa, TASK_QUEUE_QUEUED); + if (enumerator->enumerate(enumerator, &task)) + { + job = (job_t*)initiate_tasks_job_create(ike_sa->get_id(ike_sa)); + } + enumerator->destroy(enumerator); + + return job; +} + +/** * Establish the new replacement IKE_SA */ static void establish_new(private_ike_rekey_t *this) { if (this->new_sa) { + job_t *job; + this->new_sa->set_state(this->new_sa, IKE_ESTABLISHED); DBG0(DBG_IKE, "IKE_SA %s[%d] rekeyed between %H[%Y]...%H[%Y]", this->new_sa->get_name(this->new_sa), @@ -85,7 +107,14 @@ static void establish_new(private_ike_rekey_t *this) this->new_sa->inherit_post(this->new_sa, this->ike_sa); charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa); + job = check_queued_tasks(this->new_sa); + /* don't queue job before checkin(), as the IKE_SA is not yet + * registered at the manager */ charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa); + if (job) + { + lib->processor->queue_job(lib->processor, job); + } this->new_sa = NULL; /* set threads active IKE_SA after checkin */ charon->bus->set_sa(charon->bus, this->ike_sa); @@ -163,6 +192,7 @@ METHOD(task_t, process_r, status_t, { case CHILD_CREATED: case CHILD_REKEYING: + case CHILD_RETRYING: case CHILD_DELETING: /* we do not allow rekeying while we have children in-progress */ DBG1(DBG_IKE, "peer initiated rekeying, but a child is half-open"); @@ -209,6 +239,12 @@ METHOD(task_t, build_r, status_t, this->public.task.build = _build_r_delete; this->public.task.process = _process_r_delete; + /* the peer does have to delete the IKE_SA. If it does not, we get a + * unusable IKE_SA in REKEYING state without a replacement. We consider + * this a timeout condition by the peer, and trigger a delete actively. */ + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE), 90); + return NEED_MORE; } diff --git a/src/libcharon/sa/task.c b/src/libcharon/sa/task.c index 4336b23ff..b35b58185 100644 --- a/src/libcharon/sa/task.c +++ b/src/libcharon/sa/task.c @@ -27,6 +27,7 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST, "IKE_CONFIG", "IKE_REKEY", "IKE_REAUTH", + "IKE_REAUTH_COMPLETE", "IKE_DELETE", "IKE_DPD", "IKE_VENDOR", diff --git a/src/libcharon/sa/task.h b/src/libcharon/sa/task.h index f2c4299cc..7bd3da1fe 100644 --- a/src/libcharon/sa/task.h +++ b/src/libcharon/sa/task.h @@ -22,6 +22,8 @@ #ifndef TASK_H_ #define TASK_H_ +#include <utils/utils.h> + typedef enum task_type_t task_type_t; typedef struct task_t task_t; @@ -51,8 +53,10 @@ enum task_type_t { TASK_IKE_CONFIG, /** rekey an IKE_SA */ TASK_IKE_REKEY, - /** reestablish a complete IKE_SA */ + /** reestablish a complete IKE_SA, break-before-make */ TASK_IKE_REAUTH, + /** completion task for make-before-break IKE_SA re-authentication */ + TASK_IKE_REAUTH_COMPLETE, /** delete an IKE_SA */ TASK_IKE_DELETE, /** liveness check */ diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c index 7e55d6b0f..d6ff3c8c5 100644 --- a/src/libcharon/sa/trap_manager.c +++ b/src/libcharon/sa/trap_manager.c @@ -65,6 +65,11 @@ struct private_trap_manager_t { * listener to track acquiring IKE_SAs */ trap_listener_t listener; + + /** + * Whether to ignore traffic selectors from acquires + */ + bool ignore_acquire_ts; }; /** @@ -171,7 +176,7 @@ METHOD(trap_manager_t, install, u_int32_t, this->lock->unlock(this->lock); /* create and route CHILD_SA */ - child_sa = child_sa_create(me, other, child, reqid, FALSE); + child_sa = child_sa_create(me, other, child, reqid, FALSE, 0, 0); list = linked_list_create_with_items(me, NULL); my_ts = child->get_traffic_selectors(child, TRUE, NULL, list); @@ -353,7 +358,7 @@ METHOD(trap_manager_t, acquire, void, { ike_sa->set_peer_cfg(ike_sa, peer); } - if (ike_sa->get_version(ike_sa) == IKEV1) + if (this->ignore_acquire_ts || ike_sa->get_version(ike_sa) == IKEV1) { /* in IKEv1, don't prepend the acquiring packet TS, as we only * have a single TS that we can establish in a Quick Mode. */ src = dst = NULL; @@ -484,6 +489,8 @@ trap_manager_t *trap_manager_create(void) }, .traps = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .ignore_acquire_ts = lib->settings->get_bool(lib->settings, + "%s.ignore_acquire_ts", FALSE, lib->ns), ); charon->bus->add_listener(charon->bus, &this->listener.listener); diff --git a/src/libcharon/tests/Makefile.am b/src/libcharon/tests/Makefile.am new file mode 100644 index 000000000..c8be28594 --- /dev/null +++ b/src/libcharon/tests/Makefile.am @@ -0,0 +1,21 @@ +TESTS = libcharon_tests + +check_PROGRAMS = $(TESTS) + +libcharon_tests_SOURCES = \ + suites/test_mem_pool.c \ + libcharon_tests.h libcharon_tests.c + +libcharon_tests_CFLAGS = \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libstrongswan/tests \ + @COVERAGE_CFLAGS@ + +libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@ +libcharon_tests_LDADD = \ + $(top_builddir)/src/libcharon/libcharon.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in new file mode 100644 index 000000000..7f4f4b24e --- /dev/null +++ b/src/libcharon/tests/Makefile.in @@ -0,0 +1,874 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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@ +TESTS = libcharon_tests$(EXEEXT) +check_PROGRAMS = $(am__EXEEXT_1) +subdir = src/libcharon/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +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/split-package-version.m4 \ + $(top_srcdir)/m4/macros/with.m4 \ + $(top_srcdir)/m4/macros/enable-disable.m4 \ + $(top_srcdir)/m4/macros/add-plugin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = libcharon_tests$(EXEEXT) +am__dirstamp = $(am__leading_dot)dirstamp +am_libcharon_tests_OBJECTS = \ + suites/libcharon_tests-test_mem_pool.$(OBJEXT) \ + libcharon_tests-libcharon_tests.$(OBJEXT) +libcharon_tests_OBJECTS = $(am_libcharon_tests_OBJECTS) +libcharon_tests_DEPENDENCIES = \ + $(top_builddir)/src/libcharon/libcharon.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libcharon_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(libcharon_tests_CFLAGS) $(CFLAGS) $(libcharon_tests_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcharon_tests_SOURCES) +DIST_SOURCES = $(libcharon_tests_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BFDLIB = @BFDLIB@ +BTLIB = @BTLIB@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COVERAGE_CFLAGS = @COVERAGE_CFLAGS@ +COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +EASY_INSTALL = @EASY_INSTALL@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GEM = @GEM@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GPRBUILD = @GPRBUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MYSQLCFLAG = @MYSQLCFLAG@ +MYSQLCONFIG = @MYSQLCONFIG@ +MYSQLLIB = @MYSQLLIB@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_LIB = @OPENSSL_LIB@ +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@ +PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@ +PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@ +PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@ +PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PTHREADLIB = @PTHREADLIB@ +PYTHON = @PYTHON@ +PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +PY_TEST = @PY_TEST@ +RANLIB = @RANLIB@ +RTLIB = @RTLIB@ +RUBY = @RUBY@ +RUBYGEMDIR = @RUBYGEMDIR@ +RUBYINCLUDE = @RUBYINCLUDE@ +RUBYLIB = @RUBYLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKLIB = @SOCKLIB@ +STRIP = @STRIP@ +UNWINDLIB = @UNWINDLIB@ +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_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +aikgen_plugins = @aikgen_plugins@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +attest_plugins = @attest_plugins@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ +clearsilver_LIBS = @clearsilver_LIBS@ +cmd_plugins = @cmd_plugins@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dbusservicedir = @dbusservicedir@ +dev_headers = @dev_headers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +fips_mode = @fips_mode@ +gtk_CFLAGS = @gtk_CFLAGS@ +gtk_LIBS = @gtk_LIBS@ +h_plugins = @h_plugins@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +imcvdir = @imcvdir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ +ipsecdir = @ipsecdir@ +ipsecgroup = @ipsecgroup@ +ipseclibdir = @ipseclibdir@ +ipsecuser = @ipsecuser@ +json_CFLAGS = @json_CFLAGS@ +json_LIBS = @json_LIBS@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libiptc_CFLAGS = @libiptc_CFLAGS@ +libiptc_LIBS = @libiptc_LIBS@ +linux_headers = @linux_headers@ +localedir = @localedir@ +localstatedir = @localstatedir@ +maemo_CFLAGS = @maemo_CFLAGS@ +maemo_LIBS = @maemo_LIBS@ +manager_plugins = @manager_plugins@ +mandir = @mandir@ +medsrv_plugins = @medsrv_plugins@ +mkdir_p = @mkdir_p@ +nm_CFLAGS = @nm_CFLAGS@ +nm_LIBS = @nm_LIBS@ +nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ +oldincludedir = @oldincludedir@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ +pdfdir = @pdfdir@ +piddir = @piddir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pki_plugins = @pki_plugins@ +plugindir = @plugindir@ +pool_plugins = @pool_plugins@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +random_device = @random_device@ +resolv_conf = @resolv_conf@ +routing_table = @routing_table@ +routing_table_prio = @routing_table_prio@ +s_plugins = @s_plugins@ +sbindir = @sbindir@ +scepclient_plugins = @scepclient_plugins@ +scripts_plugins = @scripts_plugins@ +sharedstatedir = @sharedstatedir@ +soup_CFLAGS = @soup_CFLAGS@ +soup_LIBS = @soup_LIBS@ +srcdir = @srcdir@ +starter_plugins = @starter_plugins@ +strongswan_conf = @strongswan_conf@ +strongswan_options = @strongswan_options@ +swanctldir = @swanctldir@ +sysconfdir = @sysconfdir@ +systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@ +systemd_daemon_LIBS = @systemd_daemon_LIBS@ +systemd_journal_CFLAGS = @systemd_journal_CFLAGS@ +systemd_journal_LIBS = @systemd_journal_LIBS@ +systemdsystemunitdir = @systemdsystemunitdir@ +t_plugins = @t_plugins@ +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@ +libcharon_tests_SOURCES = \ + suites/test_mem_pool.c \ + libcharon_tests.h libcharon_tests.c + +libcharon_tests_CFLAGS = \ + -I$(top_srcdir)/src/libcharon \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libstrongswan/tests \ + @COVERAGE_CFLAGS@ + +libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@ +libcharon_tests_LDADD = \ + $(top_builddir)/src/libcharon/libcharon.la \ + $(top_builddir)/src/libhydra/libhydra.la \ + $(top_builddir)/src/libstrongswan/libstrongswan.la \ + $(top_builddir)/src/libstrongswan/tests/libtest.la + +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/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/libcharon/tests/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-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +suites/$(am__dirstamp): + @$(MKDIR_P) suites + @: > suites/$(am__dirstamp) +suites/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) suites/$(DEPDIR) + @: > suites/$(DEPDIR)/$(am__dirstamp) +suites/libcharon_tests-test_mem_pool.$(OBJEXT): \ + suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp) + +libcharon_tests$(EXEEXT): $(libcharon_tests_OBJECTS) $(libcharon_tests_DEPENDENCIES) $(EXTRA_libcharon_tests_DEPENDENCIES) + @rm -f libcharon_tests$(EXEEXT) + $(AM_V_CCLD)$(libcharon_tests_LINK) $(libcharon_tests_OBJECTS) $(libcharon_tests_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f suites/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcharon_tests-libcharon_tests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +suites/libcharon_tests-test_mem_pool.o: suites/test_mem_pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_mem_pool.o -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo -c -o suites/libcharon_tests-test_mem_pool.o `test -f 'suites/test_mem_pool.c' || echo '$(srcdir)/'`suites/test_mem_pool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_mem_pool.c' object='suites/libcharon_tests-test_mem_pool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_mem_pool.o `test -f 'suites/test_mem_pool.c' || echo '$(srcdir)/'`suites/test_mem_pool.c + +suites/libcharon_tests-test_mem_pool.obj: suites/test_mem_pool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_mem_pool.obj -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo -c -o suites/libcharon_tests-test_mem_pool.obj `if test -f 'suites/test_mem_pool.c'; then $(CYGPATH_W) 'suites/test_mem_pool.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_mem_pool.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_mem_pool.c' object='suites/libcharon_tests-test_mem_pool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_mem_pool.obj `if test -f 'suites/test_mem_pool.c'; then $(CYGPATH_W) 'suites/test_mem_pool.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_mem_pool.c'; fi` + +libcharon_tests-libcharon_tests.o: libcharon_tests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT libcharon_tests-libcharon_tests.o -MD -MP -MF $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo -c -o libcharon_tests-libcharon_tests.o `test -f 'libcharon_tests.c' || echo '$(srcdir)/'`libcharon_tests.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo $(DEPDIR)/libcharon_tests-libcharon_tests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcharon_tests.c' object='libcharon_tests-libcharon_tests.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o libcharon_tests-libcharon_tests.o `test -f 'libcharon_tests.c' || echo '$(srcdir)/'`libcharon_tests.c + +libcharon_tests-libcharon_tests.obj: libcharon_tests.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT libcharon_tests-libcharon_tests.obj -MD -MP -MF $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo -c -o libcharon_tests-libcharon_tests.obj `if test -f 'libcharon_tests.c'; then $(CYGPATH_W) 'libcharon_tests.c'; else $(CYGPATH_W) '$(srcdir)/libcharon_tests.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo $(DEPDIR)/libcharon_tests-libcharon_tests.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcharon_tests.c' object='libcharon_tests-libcharon_tests.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o libcharon_tests-libcharon_tests.obj `if test -f 'libcharon_tests.c'; then $(CYGPATH_W) 'libcharon_tests.c'; else $(CYGPATH_W) '$(srcdir)/libcharon_tests.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +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 + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +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: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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) + -rm -f suites/$(DEPDIR)/$(am__dirstamp) + -rm -f suites/$(am__dirstamp) + +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-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) suites/$(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-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) suites/$(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: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am 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-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 tags-am uninstall uninstall-am + + +# 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/tests/libcharon_tests.c b/src/libcharon/tests/libcharon_tests.c new file mode 100644 index 000000000..1ed0f0c95 --- /dev/null +++ b/src/libcharon/tests/libcharon_tests.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 <test_runner.h> +#include <hydra.h> +#include <daemon.h> + +/* declare test suite constructors */ +#define TEST_SUITE(x) test_suite_t* x(); +#define TEST_SUITE_DEPEND(x, ...) TEST_SUITE(x) +#include "libcharon_tests.h" +#undef TEST_SUITE +#undef TEST_SUITE_DEPEND + +static test_configuration_t tests[] = { +#define TEST_SUITE(x) \ + { .suite = x, }, +#define TEST_SUITE_DEPEND(x, type, args) \ + { .suite = x, .feature = PLUGIN_DEPENDS(type, args) }, +#include "libcharon_tests.h" + { .suite = NULL, } +}; + +static bool test_runner_init(bool init) +{ + if (init) + { + libhydra_init(); + libcharon_init(); + } + else + { + lib->processor->set_threads(lib->processor, 0); + lib->processor->cancel(lib->processor); + libcharon_deinit(); + libhydra_deinit(); + } + return TRUE; +} + +int main(int argc, char *argv[]) +{ + return test_runner_run("libcharon", tests, test_runner_init); +} diff --git a/src/libcharon/tests/libcharon_tests.h b/src/libcharon/tests/libcharon_tests.h new file mode 100644 index 000000000..dc9681aeb --- /dev/null +++ b/src/libcharon/tests/libcharon_tests.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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. + */ + +TEST_SUITE(mem_pool_suite_create) diff --git a/src/libcharon/tests/suites/test_mem_pool.c b/src/libcharon/tests/suites/test_mem_pool.c new file mode 100644 index 000000000..4204d4bab --- /dev/null +++ b/src/libcharon/tests/suites/test_mem_pool.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2014 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 "test_suite.h" + +#include <attributes/mem_pool.h> + +static void assert_host(char *expected, host_t *host) +{ + if (!expected) + { + ck_assert_msg(!host, "not epxecting IP != %+H", host); + } + else + { + host_t *verifier; + verifier = host_create_from_string(expected, 0); + ck_assert_msg(host, "expected IP %+H != NULL", verifier); + ck_assert_msg(verifier->ip_equals(verifier, host), "expected IP %+H != " + "%+H", verifier, host);; + verifier->destroy(verifier); + } +} + +static void assert_acquire(mem_pool_t *pool, char *requested, char *expected, + mem_pool_op_t operation) +{ + identification_t *id; + host_t *req, *acquired; + + id = identification_create_from_string("tester"); + req = host_create_from_string(requested, 0); + + acquired = pool->acquire_address(pool, id, req, operation, NULL); + assert_host(expected, acquired); + DESTROY_IF(acquired); + + req->destroy(req); + id->destroy(id); +} + +static void assert_acquires_new(mem_pool_t *pool, char *pattern, int first) +{ + char expected[16]; + int i; + + for (i = 0; i < pool->get_size(pool); i++) + { + snprintf(expected, sizeof(expected), pattern, first + i); + assert_acquire(pool, "0.0.0.0", expected, MEM_POOL_NEW); + ck_assert_int_eq(i + 1, pool->get_online(pool)); + } + assert_acquire(pool, "0.0.0.0", NULL, MEM_POOL_NEW); +} + +START_TEST(test_config) +{ + mem_pool_t *pool; + + pool = mem_pool_create("test", NULL, 0); + ck_assert_int_eq(0, pool->get_size(pool)); + assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW); + assert_acquire(pool, "10.0.1.1", "10.0.1.1", MEM_POOL_NEW); + assert_acquire(pool, "0.0.0.0", "0.0.0.0", MEM_POOL_NEW); + assert_acquire(pool, "255.255.255.255", "255.255.255.255", MEM_POOL_NEW); + ck_assert_int_eq(0, pool->get_online(pool)); + pool->destroy(pool); +} +END_TEST + +START_TEST(test_cidr) +{ + mem_pool_t *pool; + host_t *base; + + base = host_create_from_string("192.168.0.0", 0); + + pool = mem_pool_create("test", base, 32); + ck_assert_int_eq(1, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 0); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 31); + ck_assert_int_eq(2, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 0); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 30); + ck_assert_int_eq(2, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 29); + ck_assert_int_eq(6, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 24); + ck_assert_int_eq(254, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + + base->destroy(base); +} +END_TEST + +START_TEST(test_cidr_offset) +{ + mem_pool_t *pool; + host_t *base; + + base = host_create_from_string("192.168.0.1", 0); + pool = mem_pool_create("test", base, 31); + ck_assert_int_eq(1, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 30); + ck_assert_int_eq(2, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + base->destroy(base); + + base = host_create_from_string("192.168.0.2", 0); + pool = mem_pool_create("test", base, 30); + ck_assert_int_eq(1, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 2); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 24); + ck_assert_int_eq(253, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 2); + pool->destroy(pool); + base->destroy(base); + + base = host_create_from_string("192.168.0.254", 0); + pool = mem_pool_create("test", base, 24); + ck_assert_int_eq(1, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 254); + pool->destroy(pool); + base->destroy(base); + + /* due to size == 0 we get the requested IP back */ + base = host_create_from_string("192.168.0.255", 0); + pool = mem_pool_create("test", base, 24); + ck_assert_int_eq(0, pool->get_size(pool)); + assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW); + pool->destroy(pool); + + base->destroy(base); +} +END_TEST + +START_TEST(test_range) +{ + mem_pool_t *pool; + host_t *from, *to; + + from = host_create_from_string("192.168.0.0", 0); + to = host_create_from_string("192.168.0.0", 0); + pool = mem_pool_create_range("test", from, to); + ck_assert_int_eq(1, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 0); + pool->destroy(pool); + + to->destroy(to); + to = host_create_from_string("192.168.0.1", 0); + pool = mem_pool_create_range("test", from, to); + ck_assert_int_eq(2, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 0); + pool->destroy(pool); + + from->destroy(from); + from = host_create_from_string("192.168.0.10", 0); + pool = mem_pool_create_range("test", from, to); + ck_assert(!pool); + + to->destroy(to); + to = host_create_from_string("192.168.0.20", 0); + pool = mem_pool_create_range("test", from, to); + ck_assert_int_eq(11, pool->get_size(pool)); + assert_acquires_new(pool, "192.168.0.%d", 10); + pool->destroy(pool); + + from->destroy(from); + from = host_create_from_string("fec::1", 0); + to->destroy(to); + to = host_create_from_string("fed::1", 0); + pool = mem_pool_create_range("test", from, to); + ck_assert(!pool); + + from->destroy(from); + to->destroy(to); +} +END_TEST + +Suite *mem_pool_suite_create() +{ + Suite *s; + TCase *tc; + + s = suite_create("mem_pool"); + + tc = tcase_create("%config-like pool"); + tcase_add_test(tc, test_config); + suite_add_tcase(s, tc); + + tc = tcase_create("cidr constructor"); + tcase_add_test(tc, test_cidr); + tcase_add_test(tc, test_cidr_offset); + suite_add_tcase(s, tc); + + tc = tcase_create("range constructor"); + tcase_add_test(tc, test_range); + suite_add_tcase(s, tc); + + return s; +} |