summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2017-04-01 16:26:44 +0200
committerYves-Alexis Perez <corsac@corsac.net>2017-04-01 16:26:44 +0200
commit05ddd767992d68bb38c7f16ece142e8c2e9ae016 (patch)
tree302c618be306d4ed3c7f9fc58a1f6aaad4dd252f /src/libcharon
parent25663e04c3ab01ef8dc9f906608282319cfea2db (diff)
downloadvyos-strongswan-05ddd767992d68bb38c7f16ece142e8c2e9ae016.tar.gz
vyos-strongswan-05ddd767992d68bb38c7f16ece142e8c2e9ae016.zip
New upstream version 5.5.2
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Android.mk2
-rw-r--r--src/libcharon/Makefile.am9
-rw-r--r--src/libcharon/Makefile.in324
-rw-r--r--src/libcharon/bus/bus.c10
-rw-r--r--src/libcharon/config/child_cfg.c35
-rw-r--r--src/libcharon/config/ike_cfg.c37
-rw-r--r--src/libcharon/config/ike_cfg.h13
-rw-r--r--src/libcharon/config/peer_cfg.c13
-rw-r--r--src/libcharon/config/peer_cfg.h16
-rw-r--r--src/libcharon/config/proposal.c24
-rw-r--r--src/libcharon/config/proposal.h9
-rw-r--r--src/libcharon/control/controller.c1
-rw-r--r--src/libcharon/daemon.c52
-rw-r--r--src/libcharon/daemon.h28
-rw-r--r--src/libcharon/kernel/kernel_interface.c11
-rw-r--r--src/libcharon/kernel/kernel_interface.h17
-rw-r--r--src/libcharon/kernel/kernel_net.h11
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in2
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_narrow.c72
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_validator.c14
-rw-r--r--src/libcharon/plugins/android_dns/Makefile.in2
-rw-r--r--src/libcharon/plugins/android_log/Makefile.in2
-rw-r--r--src/libcharon/plugins/attr/Makefile.in2
-rw-r--r--src/libcharon/plugins/attr_sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/bypass_lan/Makefile.am18
-rw-r--r--src/libcharon/plugins/bypass_lan/Makefile.in795
-rw-r--r--src/libcharon/plugins/bypass_lan/bypass_lan_listener.c295
-rw-r--r--src/libcharon/plugins/bypass_lan/bypass_lan_listener.h54
-rw-r--r--src/libcharon/plugins/bypass_lan/bypass_lan_plugin.c109
-rw-r--r--src/libcharon/plugins/bypass_lan/bypass_lan_plugin.h42
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.in2
-rw-r--r--src/libcharon/plugins/connmark/Makefile.in2
-rw-r--r--src/libcharon/plugins/connmark/connmark_plugin.c6
-rw-r--r--src/libcharon/plugins/coupling/Makefile.in2
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in2
-rw-r--r--src/libcharon/plugins/dnscert/Makefile.in2
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_dynamic/eap_dynamic.c12
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in2
-rw-r--r--src/libcharon/plugins/error_notify/Makefile.in2
-rw-r--r--src/libcharon/plugins/ext_auth/Makefile.in2
-rw-r--r--src/libcharon/plugins/farp/Makefile.in2
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.c2
-rw-r--r--src/libcharon/plugins/forecast/Makefile.in2
-rw-r--r--src/libcharon/plugins/forecast/forecast_listener.c2
-rw-r--r--src/libcharon/plugins/ha/Makefile.in2
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c8
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c15
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_iph/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_libipsec/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_netlink/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c56
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c269
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c64
-rw-r--r--src/libcharon/plugins/kernel_pfkey/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c45
-rw-r--r--src/libcharon/plugins/kernel_pfroute/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c197
-rw-r--r--src/libcharon/plugins/kernel_wfp/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c4
-rw-r--r--src/libcharon/plugins/led/Makefile.in2
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in2
-rw-r--r--src/libcharon/plugins/lookip/Makefile.in2
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c81
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in2
-rw-r--r--src/libcharon/plugins/osx_attr/Makefile.in2
-rw-r--r--src/libcharon/plugins/p_cscf/Makefile.in2
-rw-r--r--src/libcharon/plugins/radattr/Makefile.in2
-rw-r--r--src/libcharon/plugins/resolve/Makefile.in2
-rw-r--r--src/libcharon/plugins/smp/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_win/Makefile.in2
-rw-r--r--src/libcharon/plugins/sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c10
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c124
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c20
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c10
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_plugin.c2
-rw-r--r--src/libcharon/plugins/systime_fix/Makefile.in2
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.in2
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in2
-rw-r--r--src/libcharon/plugins/uci/Makefile.in2
-rw-r--r--src/libcharon/plugins/unity/Makefile.in2
-rw-r--r--src/libcharon/plugins/unity/unity_handler.c5
-rw-r--r--src/libcharon/plugins/updown/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/README.md109
-rw-r--r--src/libcharon/plugins/vici/perl/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/python/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/python/vici/protocol.py13
-rw-r--r--src/libcharon/plugins/vici/python/vici/session.py6
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.in2
-rw-r--r--src/libcharon/plugins/vici/ruby/lib/vici.rb4
-rw-r--r--src/libcharon/plugins/vici/vici_attribute.c12
-rw-r--r--src/libcharon/plugins/vici/vici_authority.c107
-rw-r--r--src/libcharon/plugins/vici/vici_config.c326
-rw-r--r--src/libcharon/plugins/vici/vici_config.h2
-rw-r--r--src/libcharon/plugins/vici/vici_control.c141
-rw-r--r--src/libcharon/plugins/vici/vici_cred.c210
-rw-r--r--src/libcharon/plugins/vici/vici_dispatcher.c6
-rw-r--r--src/libcharon/plugins/vici/vici_logger.c7
-rw-r--r--src/libcharon/plugins/vici/vici_query.c96
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_noauth/Makefile.in2
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.in2
-rw-r--r--src/libcharon/processing/jobs/delete_ike_sa_job.c3
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.c21
-rw-r--r--src/libcharon/processing/jobs/start_action_job.c4
-rw-r--r--src/libcharon/sa/child_sa.c19
-rw-r--r--src/libcharon/sa/ike_sa.c45
-rw-r--r--src/libcharon/sa/ike_sa.h18
-rw-r--r--src/libcharon/sa/ike_sa_manager.c4
-rw-r--r--src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c4
-rw-r--r--src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c4
-rw-r--r--src/libcharon/sa/ikev1/iv_manager.c355
-rw-r--r--src/libcharon/sa/ikev1/iv_manager.h120
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.c259
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.h33
-rw-r--r--src/libcharon/sa/ikev1/phase1.c70
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c29
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c21
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c39
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c6
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.h6
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c94
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_auth.c10
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c32
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mid_sync.c264
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mid_sync.h74
-rw-r--r--src/libcharon/sa/shunt_manager.c90
-rw-r--r--src/libcharon/sa/shunt_manager.h13
-rw-r--r--src/libcharon/sa/task.c1
-rw-r--r--src/libcharon/sa/task.h2
-rw-r--r--src/libcharon/sa/task_manager.h10
-rw-r--r--src/libcharon/tests/Makefile.am1
-rw-r--r--src/libcharon/tests/Makefile.in21
-rw-r--r--src/libcharon/tests/exchange_tests.h1
-rw-r--r--src/libcharon/tests/libcharon_tests.c2
-rw-r--r--src/libcharon/tests/suites/test_ike_mid_sync.c535
-rw-r--r--src/libcharon/tests/suites/test_proposal.c26
-rw-r--r--src/libcharon/tests/utils/exchange_test_helper.c2
165 files changed, 5363 insertions, 1001 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index 4f3d78c6d..1a8e068d1 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -106,6 +106,7 @@ sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.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 \
@@ -117,6 +118,7 @@ sa/ikev2/tasks/ike_verify_peer_cert.c sa/ikev2/tasks/ike_verify_peer_cert.h
libcharon_la_SOURCES += \
sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+sa/ikev1/iv_manager.c sa/ikev1/iv_manager.h \
sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index e530205e8..8461d6230 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -105,6 +105,7 @@ sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \
sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.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 \
@@ -118,6 +119,7 @@ endif
if USE_IKEV1
libcharon_la_SOURCES += \
sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+sa/ikev1/iv_manager.c sa/ikev1/iv_manager.h \
sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
@@ -226,6 +228,13 @@ if MONOLITHIC
endif
endif
+if USE_BYPASS_LAN
+ SUBDIRS += plugins/bypass_lan
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/bypass_lan/libstrongswan-bypass-lan.la
+endif
+endif
+
if USE_FORECAST
SUBDIRS += plugins/forecast
if MONOLITHIC
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index e82e67b8f..8f6dc89a3 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -105,6 +105,7 @@ host_triplet = @host@
@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+@USE_IKEV2_TRUE@sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.h \
@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 \
@@ -116,6 +117,7 @@ host_triplet = @host@
@USE_IKEV1_TRUE@am__append_2 = \
@USE_IKEV1_TRUE@sa/ikev1/keymat_v1.c sa/ikev1/keymat_v1.h \
+@USE_IKEV1_TRUE@sa/ikev1/iv_manager.c sa/ikev1/iv_manager.h \
@USE_IKEV1_TRUE@sa/ikev1/task_manager_v1.c sa/ikev1/task_manager_v1.h \
@USE_IKEV1_TRUE@sa/ikev1/authenticators/psk_v1_authenticator.c sa/ikev1/authenticators/psk_v1_authenticator.h \
@USE_IKEV1_TRUE@sa/ikev1/authenticators/pubkey_v1_authenticator.c sa/ikev1/authenticators/pubkey_v1_authenticator.h \
@@ -161,136 +163,138 @@ host_triplet = @host@
@MONOLITHIC_TRUE@@USE_SOCKET_WIN_TRUE@am__append_13 = plugins/socket_win/libstrongswan-socket-win.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_P_CSCF_TRUE@am__append_88 = plugins/p_cscf
-@MONOLITHIC_TRUE@@USE_P_CSCF_TRUE@am__append_89 = plugins/p_cscf/libstrongswan-p-cscf.la
-@USE_ANDROID_DNS_TRUE@am__append_90 = plugins/android_dns
-@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_91 = plugins/android_dns/libstrongswan-android-dns.la
-@USE_ANDROID_LOG_TRUE@am__append_92 = plugins/android_log
-@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_93 = plugins/android_log/libstrongswan-android-log.la
-@USE_HA_TRUE@am__append_94 = plugins/ha
-@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_95 = plugins/ha/libstrongswan-ha.la
-@USE_KERNEL_PFKEY_TRUE@am__append_96 = plugins/kernel_pfkey
-@MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE@am__append_97 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
-@USE_KERNEL_PFROUTE_TRUE@am__append_98 = plugins/kernel_pfroute
-@MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE@am__append_99 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
-@USE_KERNEL_NETLINK_TRUE@am__append_100 = plugins/kernel_netlink
-@MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE@am__append_101 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
-@USE_KERNEL_LIBIPSEC_TRUE@am__append_102 = plugins/kernel_libipsec
-@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_103 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
-@USE_KERNEL_WFP_TRUE@am__append_104 = plugins/kernel_wfp
-@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_105 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
-@USE_KERNEL_IPH_TRUE@am__append_106 = plugins/kernel_iph
-@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_107 = plugins/kernel_iph/libstrongswan-kernel-iph.la
-@USE_WHITELIST_TRUE@am__append_108 = plugins/whitelist
-@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_109 = plugins/whitelist/libstrongswan-whitelist.la
-@USE_LOOKIP_TRUE@am__append_110 = plugins/lookip
-@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_111 = plugins/lookip/libstrongswan-lookip.la
-@USE_ERROR_NOTIFY_TRUE@am__append_112 = plugins/error_notify
-@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_113 = plugins/error_notify/libstrongswan-error-notify.la
-@USE_CERTEXPIRE_TRUE@am__append_114 = plugins/certexpire
-@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_115 = plugins/certexpire/libstrongswan-certexpire.la
-@USE_SYSTIME_FIX_TRUE@am__append_116 = plugins/systime_fix
-@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_117 = plugins/systime_fix/libstrongswan-systime-fix.la
-@USE_LED_TRUE@am__append_118 = plugins/led
-@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_119 = plugins/led/libstrongswan-led.la
-@USE_DUPLICHECK_TRUE@am__append_120 = plugins/duplicheck
-@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_121 = plugins/duplicheck/libstrongswan-duplicheck.la
-@USE_COUPLING_TRUE@am__append_122 = plugins/coupling
-@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_123 = plugins/coupling/libstrongswan-coupling.la
-@USE_RADATTR_TRUE@am__append_124 = plugins/radattr
-@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_125 = plugins/radattr/libstrongswan-radattr.la
-@USE_UCI_TRUE@am__append_126 = plugins/uci
-@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_127 = plugins/uci/libstrongswan-uci.la
-@USE_ADDRBLOCK_TRUE@am__append_128 = plugins/addrblock
-@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_129 = plugins/addrblock/libstrongswan-addrblock.la
-@USE_UNITY_TRUE@am__append_130 = plugins/unity
-@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_131 = plugins/unity/libstrongswan-unity.la
-@USE_XAUTH_GENERIC_TRUE@am__append_132 = plugins/xauth_generic
-@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_133 = plugins/xauth_generic/libstrongswan-xauth-generic.la
-@USE_XAUTH_EAP_TRUE@am__append_134 = plugins/xauth_eap
-@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_135 = plugins/xauth_eap/libstrongswan-xauth-eap.la
-@USE_XAUTH_PAM_TRUE@am__append_136 = plugins/xauth_pam
-@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_137 = plugins/xauth_pam/libstrongswan-xauth-pam.la
-@USE_XAUTH_NOAUTH_TRUE@am__append_138 = plugins/xauth_noauth
-@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_139 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
-@USE_RESOLVE_TRUE@am__append_140 = plugins/resolve
-@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_141 = plugins/resolve/libstrongswan-resolve.la
-@USE_ATTR_TRUE@am__append_142 = plugins/attr
-@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_143 = plugins/attr/libstrongswan-attr.la
-@USE_ATTR_SQL_TRUE@am__append_144 = plugins/attr_sql
-@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_145 = plugins/attr_sql/libstrongswan-attr-sql.la
+@USE_BYPASS_LAN_TRUE@am__append_16 = plugins/bypass_lan
+@MONOLITHIC_TRUE@@USE_BYPASS_LAN_TRUE@am__append_17 = plugins/bypass_lan/libstrongswan-bypass-lan.la
+@USE_FORECAST_TRUE@am__append_18 = plugins/forecast
+@MONOLITHIC_TRUE@@USE_FORECAST_TRUE@am__append_19 = plugins/forecast/libstrongswan-forecast.la
+@USE_FARP_TRUE@am__append_20 = plugins/farp
+@MONOLITHIC_TRUE@@USE_FARP_TRUE@am__append_21 = plugins/farp/libstrongswan-farp.la
+@USE_STROKE_TRUE@am__append_22 = plugins/stroke
+@MONOLITHIC_TRUE@@USE_STROKE_TRUE@am__append_23 = plugins/stroke/libstrongswan-stroke.la
+@USE_VICI_TRUE@am__append_24 = plugins/vici
+@MONOLITHIC_TRUE@@USE_VICI_TRUE@am__append_25 = plugins/vici/libstrongswan-vici.la
+@USE_SMP_TRUE@am__append_26 = plugins/smp
+@MONOLITHIC_TRUE@@USE_SMP_TRUE@am__append_27 = plugins/smp/libstrongswan-smp.la
+@USE_SQL_TRUE@am__append_28 = plugins/sql
+@MONOLITHIC_TRUE@@USE_SQL_TRUE@am__append_29 = plugins/sql/libstrongswan-sql.la
+@USE_DNSCERT_TRUE@am__append_30 = plugins/dnscert
+@MONOLITHIC_TRUE@@USE_DNSCERT_TRUE@am__append_31 = plugins/dnscert/libstrongswan-dnscert.la
+@USE_IPSECKEY_TRUE@am__append_32 = plugins/ipseckey
+@MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE@am__append_33 = plugins/ipseckey/libstrongswan-ipseckey.la
+@USE_UPDOWN_TRUE@am__append_34 = plugins/updown
+@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_35 = plugins/updown/libstrongswan-updown.la
+@USE_EXT_AUTH_TRUE@am__append_36 = plugins/ext_auth
+@MONOLITHIC_TRUE@@USE_EXT_AUTH_TRUE@am__append_37 = plugins/ext_auth/libstrongswan-ext-auth.la
+@USE_EAP_IDENTITY_TRUE@am__append_38 = plugins/eap_identity
+@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_39 = plugins/eap_identity/libstrongswan-eap-identity.la
+@USE_EAP_SIM_TRUE@am__append_40 = plugins/eap_sim
+@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_41 = plugins/eap_sim/libstrongswan-eap-sim.la
+@USE_EAP_SIM_FILE_TRUE@am__append_42 = plugins/eap_sim_file
+@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_43 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+@USE_EAP_SIM_PCSC_TRUE@am__append_44 = plugins/eap_sim_pcsc
+@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_45 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
+@USE_EAP_SIMAKA_SQL_TRUE@am__append_46 = plugins/eap_simaka_sql
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_47 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_48 = plugins/eap_simaka_pseudonym
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_49 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_50 = plugins/eap_simaka_reauth
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_51 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+@USE_EAP_AKA_TRUE@am__append_52 = plugins/eap_aka
+@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_53 = plugins/eap_aka/libstrongswan-eap-aka.la
+@USE_EAP_AKA_3GPP2_TRUE@am__append_54 = plugins/eap_aka_3gpp2
+@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_55 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_56 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_EAP_MD5_TRUE@am__append_57 = plugins/eap_md5
+@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_58 = plugins/eap_md5/libstrongswan-eap-md5.la
+@USE_EAP_GTC_TRUE@am__append_59 = plugins/eap_gtc
+@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_60 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+@USE_EAP_MSCHAPV2_TRUE@am__append_61 = plugins/eap_mschapv2
+@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_62 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+@USE_EAP_DYNAMIC_TRUE@am__append_63 = plugins/eap_dynamic
+@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_64 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
+@USE_EAP_RADIUS_TRUE@am__append_65 = plugins/eap_radius
+@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_66 = plugins/eap_radius/libstrongswan-eap-radius.la
+@USE_EAP_TLS_TRUE@am__append_67 = plugins/eap_tls
+@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_68 = plugins/eap_tls/libstrongswan-eap-tls.la
+@USE_EAP_TTLS_TRUE@am__append_69 = plugins/eap_ttls
+@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_70 = plugins/eap_ttls/libstrongswan-eap-ttls.la
+@USE_EAP_PEAP_TRUE@am__append_71 = plugins/eap_peap
+@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_72 = plugins/eap_peap/libstrongswan-eap-peap.la
+@USE_EAP_TNC_TRUE@am__append_73 = plugins/eap_tnc
+@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_74 = plugins/eap_tnc/libstrongswan-eap-tnc.la
+@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_75 = $(top_builddir)/src/libtls/libtls.la
+@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_76 = $(top_builddir)/src/libradius/libradius.la
+@USE_TNC_IFMAP_TRUE@am__append_77 = plugins/tnc_ifmap
+@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_78 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
+@USE_TNC_PDP_TRUE@am__append_79 = plugins/tnc_pdp
+@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_80 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
+@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_81 = $(top_builddir)/src/libtnccs/libtnccs.la
+@USE_MEDSRV_TRUE@am__append_82 = plugins/medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_83 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_84 = plugins/medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_85 = plugins/medcli/libstrongswan-medcli.la
+@USE_DHCP_TRUE@am__append_86 = plugins/dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_87 = plugins/dhcp/libstrongswan-dhcp.la
+@USE_OSX_ATTR_TRUE@am__append_88 = plugins/osx_attr
+@MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_89 = plugins/osx_attr/libstrongswan-osx-attr.la
+@USE_P_CSCF_TRUE@am__append_90 = plugins/p_cscf
+@MONOLITHIC_TRUE@@USE_P_CSCF_TRUE@am__append_91 = plugins/p_cscf/libstrongswan-p-cscf.la
+@USE_ANDROID_DNS_TRUE@am__append_92 = plugins/android_dns
+@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_93 = plugins/android_dns/libstrongswan-android-dns.la
+@USE_ANDROID_LOG_TRUE@am__append_94 = plugins/android_log
+@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_95 = plugins/android_log/libstrongswan-android-log.la
+@USE_HA_TRUE@am__append_96 = plugins/ha
+@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_97 = plugins/ha/libstrongswan-ha.la
+@USE_KERNEL_PFKEY_TRUE@am__append_98 = plugins/kernel_pfkey
+@MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE@am__append_99 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+@USE_KERNEL_PFROUTE_TRUE@am__append_100 = plugins/kernel_pfroute
+@MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE@am__append_101 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+@USE_KERNEL_NETLINK_TRUE@am__append_102 = plugins/kernel_netlink
+@MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE@am__append_103 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+@USE_KERNEL_LIBIPSEC_TRUE@am__append_104 = plugins/kernel_libipsec
+@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_105 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
+@USE_KERNEL_WFP_TRUE@am__append_106 = plugins/kernel_wfp
+@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_107 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
+@USE_KERNEL_IPH_TRUE@am__append_108 = plugins/kernel_iph
+@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_109 = plugins/kernel_iph/libstrongswan-kernel-iph.la
+@USE_WHITELIST_TRUE@am__append_110 = plugins/whitelist
+@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_111 = plugins/whitelist/libstrongswan-whitelist.la
+@USE_LOOKIP_TRUE@am__append_112 = plugins/lookip
+@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_113 = plugins/lookip/libstrongswan-lookip.la
+@USE_ERROR_NOTIFY_TRUE@am__append_114 = plugins/error_notify
+@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_115 = plugins/error_notify/libstrongswan-error-notify.la
+@USE_CERTEXPIRE_TRUE@am__append_116 = plugins/certexpire
+@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_117 = plugins/certexpire/libstrongswan-certexpire.la
+@USE_SYSTIME_FIX_TRUE@am__append_118 = plugins/systime_fix
+@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_119 = plugins/systime_fix/libstrongswan-systime-fix.la
+@USE_LED_TRUE@am__append_120 = plugins/led
+@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_121 = plugins/led/libstrongswan-led.la
+@USE_DUPLICHECK_TRUE@am__append_122 = plugins/duplicheck
+@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_123 = plugins/duplicheck/libstrongswan-duplicheck.la
+@USE_COUPLING_TRUE@am__append_124 = plugins/coupling
+@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_125 = plugins/coupling/libstrongswan-coupling.la
+@USE_RADATTR_TRUE@am__append_126 = plugins/radattr
+@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_127 = plugins/radattr/libstrongswan-radattr.la
+@USE_UCI_TRUE@am__append_128 = plugins/uci
+@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_129 = plugins/uci/libstrongswan-uci.la
+@USE_ADDRBLOCK_TRUE@am__append_130 = plugins/addrblock
+@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_131 = plugins/addrblock/libstrongswan-addrblock.la
+@USE_UNITY_TRUE@am__append_132 = plugins/unity
+@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_133 = plugins/unity/libstrongswan-unity.la
+@USE_XAUTH_GENERIC_TRUE@am__append_134 = plugins/xauth_generic
+@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_135 = plugins/xauth_generic/libstrongswan-xauth-generic.la
+@USE_XAUTH_EAP_TRUE@am__append_136 = plugins/xauth_eap
+@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_137 = plugins/xauth_eap/libstrongswan-xauth-eap.la
+@USE_XAUTH_PAM_TRUE@am__append_138 = plugins/xauth_pam
+@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_139 = plugins/xauth_pam/libstrongswan-xauth-pam.la
+@USE_XAUTH_NOAUTH_TRUE@am__append_140 = plugins/xauth_noauth
+@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_141 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
+@USE_RESOLVE_TRUE@am__append_142 = plugins/resolve
+@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_143 = plugins/resolve/libstrongswan-resolve.la
+@USE_ATTR_TRUE@am__append_144 = plugins/attr
+@MONOLITHIC_TRUE@@USE_ATTR_TRUE@am__append_145 = plugins/attr/libstrongswan-attr.la
+@USE_ATTR_SQL_TRUE@am__append_146 = plugins/attr_sql
+@MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE@am__append_147 = plugins/attr_sql/libstrongswan-attr-sql.la
subdir = src/libcharon
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -352,12 +356,12 @@ libcharon_la_DEPENDENCIES = \
$(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_51) \
- $(am__append_53) $(am__append_54) $(am__append_56) \
+ $(am__append_53) $(am__append_55) $(am__append_56) \
$(am__append_58) $(am__append_60) $(am__append_62) \
$(am__append_64) $(am__append_66) $(am__append_68) \
- $(am__append_70) $(am__append_72) $(am__append_73) \
- $(am__append_74) $(am__append_76) $(am__append_78) \
- $(am__append_79) $(am__append_81) $(am__append_83) \
+ $(am__append_70) $(am__append_72) $(am__append_74) \
+ $(am__append_75) $(am__append_76) $(am__append_78) \
+ $(am__append_80) $(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) $(am__append_101) \
@@ -368,7 +372,7 @@ libcharon_la_DEPENDENCIES = \
$(am__append_127) $(am__append_129) $(am__append_131) \
$(am__append_133) $(am__append_135) $(am__append_137) \
$(am__append_139) $(am__append_141) $(am__append_143) \
- $(am__append_145)
+ $(am__append_145) $(am__append_147)
am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
attributes/attributes.h attributes/attribute_provider.h \
attributes/attribute_handler.h attributes/attribute_manager.c \
@@ -492,6 +496,7 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \
sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \
sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \
+ sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.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 \
@@ -503,7 +508,8 @@ am__libcharon_la_SOURCES_DIST = attributes/attributes.c \
sa/ikev2/tasks/ike_vendor.h \
sa/ikev2/tasks/ike_verify_peer_cert.c \
sa/ikev2/tasks/ike_verify_peer_cert.h sa/ikev1/keymat_v1.c \
- sa/ikev1/keymat_v1.h sa/ikev1/task_manager_v1.c \
+ sa/ikev1/keymat_v1.h sa/ikev1/iv_manager.c \
+ sa/ikev1/iv_manager.h sa/ikev1/task_manager_v1.c \
sa/ikev1/task_manager_v1.h \
sa/ikev1/authenticators/psk_v1_authenticator.c \
sa/ikev1/authenticators/psk_v1_authenticator.h \
@@ -557,6 +563,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_dpd.lo \
@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_init.lo \
@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_natd.lo \
+@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_mid_sync.lo \
@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 \
@@ -566,6 +573,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_vendor.lo \
@USE_IKEV2_TRUE@ sa/ikev2/tasks/ike_verify_peer_cert.lo
@USE_IKEV1_TRUE@am__objects_2 = sa/ikev1/keymat_v1.lo \
+@USE_IKEV1_TRUE@ sa/ikev1/iv_manager.lo \
@USE_IKEV1_TRUE@ sa/ikev1/task_manager_v1.lo \
@USE_IKEV1_TRUE@ sa/ikev1/authenticators/psk_v1_authenticator.lo \
@USE_IKEV1_TRUE@ sa/ikev1/authenticators/pubkey_v1_authenticator.lo \
@@ -733,10 +741,11 @@ ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
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/bypass_lan 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 \
@@ -927,7 +936,6 @@ 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@
@@ -962,6 +970,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
@@ -1140,11 +1149,11 @@ libcharon_la_LIBADD = \
$(am__append_37) $(am__append_39) $(am__append_41) \
$(am__append_43) $(am__append_45) $(am__append_47) \
$(am__append_49) $(am__append_51) $(am__append_53) \
- $(am__append_54) $(am__append_56) $(am__append_58) \
+ $(am__append_55) $(am__append_56) $(am__append_58) \
$(am__append_60) $(am__append_62) $(am__append_64) \
$(am__append_66) $(am__append_68) $(am__append_70) \
- $(am__append_72) $(am__append_73) $(am__append_74) \
- $(am__append_76) $(am__append_78) $(am__append_79) \
+ $(am__append_72) $(am__append_74) $(am__append_75) \
+ $(am__append_76) $(am__append_78) $(am__append_80) \
$(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) \
@@ -1155,7 +1164,8 @@ libcharon_la_LIBADD = \
$(am__append_123) $(am__append_125) $(am__append_127) \
$(am__append_129) $(am__append_131) $(am__append_133) \
$(am__append_135) $(am__append_137) $(am__append_139) \
- $(am__append_141) $(am__append_143) $(am__append_145)
+ $(am__append_141) $(am__append_143) $(am__append_145) \
+ $(am__append_147)
EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \
@MONOLITHIC_FALSE@ $(am__append_10) $(am__append_12) \
@@ -1169,12 +1179,12 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_42) $(am__append_44) \
@MONOLITHIC_FALSE@ $(am__append_46) $(am__append_48) \
@MONOLITHIC_FALSE@ $(am__append_50) $(am__append_52) \
-@MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \
+@MONOLITHIC_FALSE@ $(am__append_54) $(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_69) \
-@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_75) \
-@MONOLITHIC_FALSE@ $(am__append_77) $(am__append_80) \
+@MONOLITHIC_FALSE@ $(am__append_71) $(am__append_73) \
+@MONOLITHIC_FALSE@ $(am__append_77) $(am__append_79) \
@MONOLITHIC_FALSE@ $(am__append_82) $(am__append_84) \
@MONOLITHIC_FALSE@ $(am__append_86) $(am__append_88) \
@MONOLITHIC_FALSE@ $(am__append_90) $(am__append_92) \
@@ -1190,7 +1200,8 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_130) $(am__append_132) \
@MONOLITHIC_FALSE@ $(am__append_134) $(am__append_136) \
@MONOLITHIC_FALSE@ $(am__append_138) $(am__append_140) \
-@MONOLITHIC_FALSE@ $(am__append_142) $(am__append_144) tests
+@MONOLITHIC_FALSE@ $(am__append_142) $(am__append_144) \
+@MONOLITHIC_FALSE@ $(am__append_146) tests
# build optional plugins
########################
@@ -1206,12 +1217,12 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_42) $(am__append_44) \
@MONOLITHIC_TRUE@ $(am__append_46) $(am__append_48) \
@MONOLITHIC_TRUE@ $(am__append_50) $(am__append_52) \
-@MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \
+@MONOLITHIC_TRUE@ $(am__append_54) $(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_69) \
-@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_75) \
-@MONOLITHIC_TRUE@ $(am__append_77) $(am__append_80) \
+@MONOLITHIC_TRUE@ $(am__append_71) $(am__append_73) \
+@MONOLITHIC_TRUE@ $(am__append_77) $(am__append_79) \
@MONOLITHIC_TRUE@ $(am__append_82) $(am__append_84) \
@MONOLITHIC_TRUE@ $(am__append_86) $(am__append_88) \
@MONOLITHIC_TRUE@ $(am__append_90) $(am__append_92) \
@@ -1227,7 +1238,8 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_130) $(am__append_132) \
@MONOLITHIC_TRUE@ $(am__append_134) $(am__append_136) \
@MONOLITHIC_TRUE@ $(am__append_138) $(am__append_140) \
-@MONOLITHIC_TRUE@ $(am__append_142) $(am__append_144) . tests
+@MONOLITHIC_TRUE@ $(am__append_142) $(am__append_144) \
+@MONOLITHIC_TRUE@ $(am__append_146) . tests
all: all-recursive
.SUFFIXES:
@@ -1594,6 +1606,8 @@ sa/ikev2/tasks/ike_init.lo: sa/ikev2/tasks/$(am__dirstamp) \
sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
sa/ikev2/tasks/ike_natd.lo: sa/ikev2/tasks/$(am__dirstamp) \
sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
+sa/ikev2/tasks/ike_mid_sync.lo: sa/ikev2/tasks/$(am__dirstamp) \
+ sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
sa/ikev2/tasks/ike_mobike.lo: sa/ikev2/tasks/$(am__dirstamp) \
sa/ikev2/tasks/$(DEPDIR)/$(am__dirstamp)
sa/ikev2/tasks/ike_rekey.lo: sa/ikev2/tasks/$(am__dirstamp) \
@@ -1619,6 +1633,8 @@ sa/ikev1/$(DEPDIR)/$(am__dirstamp):
@: > sa/ikev1/$(DEPDIR)/$(am__dirstamp)
sa/ikev1/keymat_v1.lo: sa/ikev1/$(am__dirstamp) \
sa/ikev1/$(DEPDIR)/$(am__dirstamp)
+sa/ikev1/iv_manager.lo: sa/ikev1/$(am__dirstamp) \
+ sa/ikev1/$(DEPDIR)/$(am__dirstamp)
sa/ikev1/task_manager_v1.lo: sa/ikev1/$(am__dirstamp) \
sa/ikev1/$(DEPDIR)/$(am__dirstamp)
sa/ikev1/authenticators/$(am__dirstamp):
@@ -1824,6 +1840,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@sa/$(DEPDIR)/trap_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/eap/$(DEPDIR)/eap_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/eap/$(DEPDIR)/eap_method.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev1/$(DEPDIR)/iv_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev1/$(DEPDIR)/keymat_v1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev1/$(DEPDIR)/phase1.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev1/$(DEPDIR)/task_manager_v1.Plo@am__quote@
@@ -1862,6 +1879,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_dpd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_init.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_me.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@sa/ikev2/tasks/$(DEPDIR)/ike_mid_sync.Plo@am__quote@
@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@
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index 6b3cea880..f4bba872f 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -233,6 +233,7 @@ static inline void unregister_logger(private_bus_t *this, logger_t *logger)
enumerator_t *enumerator;
linked_list_t *loggers;
log_entry_t *entry, *found = NULL;
+ debug_t group;
loggers = this->loggers[DBG_MAX];
enumerator = loggers->create_enumerator(loggers);
@@ -249,17 +250,16 @@ static inline void unregister_logger(private_bus_t *this, logger_t *logger)
if (found)
{
- level_t level = LEVEL_SILENT, vlevel = LEVEL_SILENT;
- debug_t group;
-
for (group = 0; group < DBG_MAX; group++)
{
if (found->levels[group] > LEVEL_SILENT)
{
+ level_t level = LEVEL_SILENT, vlevel = LEVEL_SILENT;
+
loggers = this->loggers[group];
loggers->remove(loggers, found, NULL);
- loggers->find_first(loggers, (linked_list_match_t)find_max_levels, NULL,
- &group, &level, &vlevel);
+ loggers->find_first(loggers, (linked_list_match_t)find_max_levels,
+ NULL, &group, &level, &vlevel);
set_level(&this->max_level[group], level);
set_level(&this->max_vlevel[group], vlevel);
}
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 6a9c342f4..3c6dd5198 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -249,7 +249,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*,
{
proposal->strip_dh(proposal, MODP_NONE);
}
- selected = proposal->select(proposal, match, private);
+ selected = proposal->select(proposal, match, prefer_self, private);
if (selected)
{
DBG2(DBG_CFG, "received proposals: %#P", proposals);
@@ -306,25 +306,30 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
{
e1 = this->other_ts->create_enumerator(this->other_ts);
}
- /* In a first step, replace "dynamic" TS with the host list */
+ /* in a first step, replace "dynamic" TS with the host list */
while (e1->enumerate(e1, &ts1))
{
- if (hosts && hosts->get_count(hosts) &&
- ts1->is_dynamic(ts1))
- {
- e2 = hosts->create_enumerator(hosts);
- while (e2->enumerate(e2, &host))
+ if (hosts && hosts->get_count(hosts))
+ { /* set hosts if TS is dynamic or as initiator in transport mode */
+ bool dynamic = ts1->is_dynamic(ts1);
+ if (dynamic || (this->mode == MODE_TRANSPORT && !this->proxy_mode &&
+ !supplied))
{
- ts2 = ts1->clone(ts1);
- ts2->set_address(ts2, host);
- derived->insert_last(derived, ts2);
+ e2 = hosts->create_enumerator(hosts);
+ while (e2->enumerate(e2, &host))
+ {
+ ts2 = ts1->clone(ts1);
+ if (dynamic || !host->is_anyaddr(host))
+ { /* don't make regular TS larger than they were */
+ ts2->set_address(ts2, host);
+ }
+ derived->insert_last(derived, ts2);
+ }
+ e2->destroy(e2);
+ continue;
}
- e2->destroy(e2);
- }
- else
- {
- derived->insert_last(derived, ts1->clone(ts1));
}
+ derived->insert_last(derived, ts1->clone(ts1));
}
e1->destroy(e1);
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index 7d52ac88f..480dd3720 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2016 Tobias Brunner
+ * Copyright (C) 2012-2017 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -339,7 +339,7 @@ METHOD(ike_cfg_t, select_proposal, proposal_t*,
}
while (match_enum->enumerate(match_enum, (void**)&match))
{
- selected = proposal->select(proposal, match, private);
+ selected = proposal->select(proposal, match, prefer_self, private);
if (selected)
{
DBG2(DBG_CFG, "received proposals: %#P", proposals);
@@ -559,6 +559,39 @@ int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
/**
* Described in header.
*/
+bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
+{
+ private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
+ enumerator_t *enumerator;
+ host_t *host;
+ char *str;
+ bool found = FALSE;
+
+ if (local)
+ {
+ enumerator = this->my_hosts->create_enumerator(this->my_hosts);
+ }
+ else
+ {
+ enumerator = this->other_hosts->create_enumerator(this->other_hosts);
+ }
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ host = host_create_from_string(str, 0);
+ if (host && addr->ip_equals(addr, host))
+ {
+ found = TRUE;
+ break;
+ }
+ DESTROY_IF(host);
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Described in header.
+ */
ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
char *me, uint16_t my_port,
char *other, uint16_t other_port,
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index afcb772fe..4d37264f6 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2016 Tobias Brunner
+ * Copyright (C) 2012-2017 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -266,4 +266,15 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
*/
int ike_cfg_get_family(ike_cfg_t *this, bool local);
+/**
+ * Determine if the given address was explicitly configured as local or remote
+ * address.
+ *
+ * @param this ike config to check
+ * @param addr address to check
+ * @param local TRUE to check local addresses, FALSE for remote
+ * @return TRUE if address was configured
+ */
+bool ike_cfg_has_address(ike_cfg_t *this, host_t *addr, bool local);
+
#endif /** IKE_CFG_H_ @}*/
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index 6463c7a36..5d7ab076e 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2016 Tobias Brunner
+ * Copyright (C) 2007-2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -164,7 +164,7 @@ struct private_peer_cfg_t {
/**
* Name of the mediation connection to mediate through
*/
- peer_cfg_t *mediated_by;
+ char *mediated_by;
/**
* ID of our peer at the mediation server (= leftid of the peer's conn with
@@ -235,6 +235,7 @@ METHOD(enumerator_t, child_cfgs_replace_enumerate, bool,
{
break;
}
+ this->wrapped->destroy(this->wrapped);
this->wrapped = this->added->create_enumerator(this->added);
this->add = TRUE;
}
@@ -579,7 +580,7 @@ METHOD(peer_cfg_t, is_mediation, bool,
return this->mediation;
}
-METHOD(peer_cfg_t, get_mediated_by, peer_cfg_t*,
+METHOD(peer_cfg_t, get_mediated_by, char*,
private_peer_cfg_t *this)
{
return this->mediated_by;
@@ -682,7 +683,7 @@ METHOD(peer_cfg_t, equals, bool,
auth_cfg_equal(this, other)
#ifdef ME
&& this->mediation == other->mediation &&
- this->mediated_by == other->mediated_by &&
+ streq(this->mediated_by, other->mediated_by) &&
(this->peer_id == other->peer_id ||
(this->peer_id && other->peer_id &&
this->peer_id->equals(this->peer_id, other->peer_id)))
@@ -712,8 +713,8 @@ METHOD(peer_cfg_t, destroy, void,
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->pools->destroy_function(this->pools, free);
#ifdef ME
- DESTROY_IF(this->mediated_by);
DESTROY_IF(this->peer_id);
+ free(this->mediated_by);
#endif /* ME */
this->mutex->destroy(this->mutex);
free(this->name);
@@ -801,7 +802,7 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg,
.refcount = 1,
#ifdef ME
.mediation = data->mediation,
- .mediated_by = data->mediated_by,
+ .mediated_by = strdupnull(data->mediated_by),
.peer_id = data->peer_id,
#endif /* ME */
);
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 8e4d5331c..b294ae72f 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2016 Tobias Brunner
+ * Copyright (C) 2007-2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -319,14 +319,14 @@ struct peer_cfg_t {
*
* @return TRUE, if this is a mediation connection
*/
- bool (*is_mediation) (peer_cfg_t *this);
+ bool (*is_mediation)(peer_cfg_t *this);
/**
- * Get peer_cfg of the connection this one is mediated through.
+ * Get name of the connection this one is mediated through.
*
- * @return the peer_cfg of the mediation connection
+ * @return the name of the mediation connection
*/
- peer_cfg_t* (*get_mediated_by) (peer_cfg_t *this);
+ char* (*get_mediated_by)(peer_cfg_t *this);
/**
* Get the id of the other peer at the mediation server.
@@ -338,7 +338,7 @@ struct peer_cfg_t {
*
* @return the id of the other peer
*/
- identification_t* (*get_peer_id) (peer_cfg_t *this);
+ identification_t* (*get_peer_id)(peer_cfg_t *this);
#endif /* ME */
/**
@@ -398,8 +398,8 @@ struct peer_cfg_create_t {
#ifdef ME
/** TRUE if this is a mediation connection */
bool mediation;
- /** peer_cfg_t of the mediation connection to mediate through (adopted) */
- peer_cfg_t *mediated_by;
+ /** peer_cfg_t of the mediation connection to mediate through (cloned) */
+ char *mediated_by;
/** ID that identifies our peer at the mediation server (adopted) */
identification_t *peer_id;
#endif /* ME */
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 011c0b8b0..a2dc113a5 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -273,7 +273,8 @@ static bool select_algo(private_proposal_t *this, proposal_t *other,
}
METHOD(proposal_t, select_proposal, proposal_t*,
- private_proposal_t *this, proposal_t *other, bool private)
+ private_proposal_t *this, proposal_t *other, bool other_remote,
+ bool private)
{
proposal_t *selected;
@@ -285,7 +286,17 @@ METHOD(proposal_t, select_proposal, proposal_t*,
return NULL;
}
- selected = proposal_create(this->protocol, other->get_number(other));
+ if (other_remote)
+ {
+ selected = proposal_create(this->protocol, other->get_number(other));
+ selected->set_spi(selected, other->get_spi(other));
+ }
+ else
+ {
+ selected = proposal_create(this->protocol, this->number);
+ selected->set_spi(selected, this->spi);
+
+ }
if (!select_algo(this, other, selected, ENCRYPTION_ALGORITHM, private) ||
!select_algo(this, other, selected, PSEUDO_RANDOM_FUNCTION, private) ||
@@ -298,7 +309,6 @@ METHOD(proposal_t, select_proposal, proposal_t*,
}
DBG2(DBG_CFG, " proposal matches");
- selected->set_spi(selected, other->get_spi(other));
return selected;
}
@@ -915,6 +925,8 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
case ECP_256_BP:
case ECP_384_BP:
case ECP_512_BP:
+ case CURVE_25519:
+ case CURVE_448:
case NTRU_128_BIT:
case NTRU_192_BIT:
case NTRU_256_BIT:
@@ -956,9 +968,12 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
case MODP_768_BIT:
/* weak */
break;
+ case MODP_1024_160:
case MODP_2048_224:
+ case MODP_2048_256:
+ /* RFC 5114 primes are of questionable source */
+ break;
case MODP_1536_BIT:
- case MODP_1024_160:
case ECP_224_BIT:
case ECP_224_BP:
case ECP_192_BIT:
@@ -966,7 +981,6 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
/* rarely used */
break;
case MODP_2048_BIT:
- case MODP_2048_256:
case MODP_1024_BIT:
add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
break;
diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h
index f9f277820..2bdf3454f 100644
--- a/src/libcharon/config/proposal.h
+++ b/src/libcharon/config/proposal.h
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2009-2016 Tobias Brunner
* Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -124,10 +125,14 @@ struct proposal_t {
* in common, a resulting proposal of this kind is created.
*
* @param other proposal to compare against
+ * @param other_remote whether other is the remote proposal from which to
+ * copy SPI and proposal number to the result,
+ * otherwise copy from this proposal
* @param private accepts algorithms allocated in a private range
* @return selected proposal, NULL if proposals don't match
*/
- proposal_t *(*select) (proposal_t *this, proposal_t *other, bool private);
+ proposal_t *(*select)(proposal_t *this, proposal_t *other,
+ bool other_remote, bool private);
/**
* Get the protocol ID of the proposal.
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index 93ff70bf3..8e7816b39 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -588,7 +588,6 @@ METHOD(controller_t, terminate_ike, status_t,
.listener = {
.public = {
.ike_state_change = _ike_state_change_terminate,
- .child_state_change = _child_state_change_terminate,
},
.logger = {
.public = {
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 532d0812e..eadc10a6a 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2016 Tobias Brunner
+ * Copyright (C) 2006-2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -87,6 +87,16 @@ struct private_daemon_t {
linked_list_t *loggers;
/**
+ * Cached log levels for default loggers
+ */
+ level_t *levels;
+
+ /**
+ * Whether to log to stdout/err by default
+ */
+ bool to_stderr;
+
+ /**
* Identifier used for syslog (in the openlog call)
*/
char *syslog_identifier;
@@ -532,7 +542,7 @@ static void load_custom_logger(private_daemon_t *this,
}
METHOD(daemon_t, load_loggers, void,
- private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
+ private_daemon_t *this)
{
enumerator_t *enumerator;
linked_list_t *current_loggers;
@@ -564,7 +574,7 @@ METHOD(daemon_t, load_loggers, void,
load_custom_logger(this, &custom_loggers[i], current_loggers);
}
- if (!this->loggers->get_count(this->loggers) && levels)
+ if (!this->loggers->get_count(this->loggers) && this->levels)
{ /* setup legacy style default loggers configured via command-line */
file_logger_t *file_logger;
sys_logger_t *sys_logger;
@@ -578,11 +588,11 @@ METHOD(daemon_t, load_loggers, void,
{
if (sys_logger)
{
- sys_logger->set_level(sys_logger, group, levels[group]);
+ sys_logger->set_level(sys_logger, group, this->levels[group]);
}
- if (to_stderr)
+ if (this->to_stderr)
{
- file_logger->set_level(file_logger, group, levels[group]);
+ file_logger->set_level(file_logger, group, this->levels[group]);
}
}
if (sys_logger)
@@ -604,13 +614,39 @@ METHOD(daemon_t, load_loggers, void,
this->mutex->unlock(this->mutex);
}
+METHOD(daemon_t, set_default_loggers, void,
+ private_daemon_t *this, level_t levels[DBG_MAX], bool to_stderr)
+{
+ debug_t group;
+
+ this->mutex->lock(this->mutex);
+ if (!levels)
+ {
+ free(this->levels);
+ this->levels = NULL;
+ }
+ else
+ {
+ if (!this->levels)
+ {
+ this->levels = calloc(sizeof(level_t), DBG_MAX);
+ }
+ for (group = 0; group < DBG_MAX; group++)
+ {
+ this->levels[group] = levels[group];
+ }
+ this->to_stderr = to_stderr;
+ }
+ this->mutex->unlock(this->mutex);
+}
+
METHOD(daemon_t, set_level, void,
private_daemon_t *this, debug_t group, level_t level)
{
enumerator_t *enumerator;
logger_entry_t *entry;
- /* we set the loglevel on ALL sys- and file-loggers */
+ /* we set the loglevel on ALL loggers */
this->mutex->lock(this->mutex);
enumerator = this->loggers->create_enumerator(this->loggers);
while (enumerator->enumerate(enumerator, &entry))
@@ -694,6 +730,7 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.bus);
this->loggers->destroy_function(this->loggers, (void*)logger_entry_destroy);
this->mutex->destroy(this->mutex);
+ free(this->levels);
free(this);
}
@@ -879,6 +916,7 @@ private_daemon_t *daemon_create()
.initialize = _initialize,
.start = _start,
.load_loggers = _load_loggers,
+ .set_default_loggers = _set_default_loggers,
.set_level = _set_level,
.bus = bus_create(),
},
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index 48b9c7ec3..a37a3148a 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2012 Tobias Brunner
+ * Copyright (C) 2006-2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -169,7 +169,7 @@
* IKE_SA.
*
* The controller, credential_manager, bus and backend_manager (config) are
- * places where a plugin ca register itself to privide information or observe
+ * places where a plugin ca register itself to provide information or observe
* and control the daemon.
*/
@@ -338,17 +338,27 @@ struct daemon_t {
/**
* Load/Reload loggers defined in strongswan.conf
*
- * @param levels optional debug levels used to create default loggers
- * if none are defined in strongswan.conf
+ * If none are defined in strongswan.conf default loggers configured via
+ * set_default_loggers() are loaded.
+ */
+ void (*load_loggers)(daemon_t *this);
+
+ /**
+ * Configure default loggers if none are defined in strongswan.conf
+ *
+ * @param levels debug levels used to create default loggers if none are
+ * defined in strongswan.conf (NULL to disable)
* @param to_stderr TRUE to log to stderr/stdout if no loggers are defined
- * in strongswan.conf
+ * in strongswan.conf (logging to syslog is always enabled)
*/
- void (*load_loggers)(daemon_t *this, level_t levels[DBG_MAX],
- bool to_stderr);
+ void (*set_default_loggers)(daemon_t *this, level_t levels[DBG_MAX],
+ bool to_stderr);
/**
- * Set the log level for the given log group for all configured file-,
- * syslog and custom-loggers.
+ * Set the log level for the given log group for all loaded loggers.
+ *
+ * This change is not persistent and gets reset if loggers are reloaded
+ * via load_loggers().
*
* @param group log group
* @param level log level
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
index 7b39a020c..ea5af9eb8 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -554,6 +554,16 @@ METHOD(kernel_interface_t, create_address_enumerator, enumerator_t*,
return this->net->create_address_enumerator(this->net, which);
}
+METHOD(kernel_interface_t, create_local_subnet_enumerator, enumerator_t*,
+ private_kernel_interface_t *this)
+{
+ if (!this->net || !this->net->create_local_subnet_enumerator)
+ {
+ return enumerator_create_empty();
+ }
+ return this->net->create_local_subnet_enumerator(this->net);
+}
+
METHOD(kernel_interface_t, add_ip, status_t,
private_kernel_interface_t *this, host_t *virtual_ip, int prefix,
char *iface)
@@ -1005,6 +1015,7 @@ kernel_interface_t *kernel_interface_create()
.get_nexthop = _get_nexthop,
.get_interface = _get_interface,
.create_address_enumerator = _create_address_enumerator,
+ .create_local_subnet_enumerator = _create_local_subnet_enumerator,
.add_ip = _add_ip,
.del_ip = _del_ip,
.add_route = _add_route,
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
index 225b40932..d601ebd4e 100644
--- a/src/libcharon/kernel/kernel_interface.h
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -57,6 +57,12 @@ typedef enum kernel_feature_t kernel_feature_t;
#include <kernel/kernel_net.h>
/**
+ * Default range for SPIs requested from kernels
+ */
+#define KERNEL_SPI_MIN 0xc0000000
+#define KERNEL_SPI_MAX 0xcfffffff
+
+/**
* Bitfield of optional features a kernel backend supports.
*
* This feature-set is for both, kernel_ipsec_t and kernel_net_t. Each
@@ -316,6 +322,17 @@ struct kernel_interface_t {
kernel_address_type_t which);
/**
+ * Creates an enumerator over all local subnets.
+ *
+ * Local subnets are subnets the host is directly connected to.
+ *
+ * The enumerator returns the network, subnet mask and interface.
+ *
+ * @return enumerator over host_t*, uint8_t, char*
+ */
+ enumerator_t *(*create_local_subnet_enumerator)(kernel_interface_t *this);
+
+ /**
* Add a virtual IP to an interface.
*
* Virtual IPs are attached to an interface. If an IP is added multiple
diff --git a/src/libcharon/kernel/kernel_net.h b/src/libcharon/kernel/kernel_net.h
index 1d78d6edd..12475b123 100644
--- a/src/libcharon/kernel/kernel_net.h
+++ b/src/libcharon/kernel/kernel_net.h
@@ -119,6 +119,17 @@ struct kernel_net_t {
kernel_address_type_t which);
/**
+ * Creates an enumerator over all local subnets.
+ *
+ * Local subnets are subnets the host is directly connected to.
+ *
+ * The enumerator returns the network, subnet mask and interface.
+ *
+ * @return enumerator over host_t*, uint8_t, char*
+ */
+ enumerator_t *(*create_local_subnet_enumerator)(kernel_net_t *this);
+
+ /**
* Add a virtual IP to an interface.
*
* Virtual IPs are attached to an interface. If an IP is added multiple
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 7917d457e..f5dfc14d7 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.c b/src/libcharon/plugins/addrblock/addrblock_narrow.c
index f85fa78d6..3b3b72ff8 100644
--- a/src/libcharon/plugins/addrblock/addrblock_narrow.c
+++ b/src/libcharon/plugins/addrblock/addrblock_narrow.c
@@ -33,17 +33,15 @@ struct private_addrblock_narrow_t {
addrblock_narrow_t public;
};
-/**
- * Check if the negotiated TS list is acceptable by X509 ipAddrBlock constraints
- */
-static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list)
+static void narrow_addrblock(private_addrblock_narrow_t *this, ike_sa_t *ike_sa,
+ linked_list_t *list)
{
- auth_cfg_t *auth;
- enumerator_t *auth_enum;
certificate_t *cert = NULL;
+ enumerator_t *enumerator;
+ auth_cfg_t *auth;
- auth_enum = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
- while (auth_enum->enumerate(auth_enum, &auth))
+ enumerator = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+ while (enumerator->enumerate(enumerator, &auth))
{
cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
if (cert)
@@ -51,7 +49,7 @@ static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list)
break;
}
}
- auth_enum->destroy(auth_enum);
+ enumerator->destroy(enumerator);
if (cert && cert->get_type(cert) == CERT_X509)
{
@@ -59,54 +57,45 @@ static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list)
if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
{
- enumerator_t *enumerator, *block_enum;
- traffic_selector_t *ts, *block_ts;
+ traffic_selector_t *ts, *block, *subset;
+ linked_list_t *original;
+
+ original = linked_list_create();
+ while (list->remove_last(list, (void**)&ts) == SUCCESS)
+ {
+ original->insert_first(original, ts);
+ }
DBG1(DBG_IKE, "checking certificate-based traffic selector "
- "constraints [RFC 3779]");
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &ts))
+ "constraints [RFC 3779]");
+ while (original->remove_first(original, (void**)&ts) == SUCCESS)
{
bool contained = FALSE;
- block_enum = x509->create_ipAddrBlock_enumerator(x509);
- while (block_enum->enumerate(block_enum, &block_ts))
+ enumerator = x509->create_ipAddrBlock_enumerator(x509);
+ while (enumerator->enumerate(enumerator, &block))
{
- if (ts->is_contained_in(ts, block_ts))
+ subset = ts->get_subset(ts, block);
+ if (subset)
{
DBG1(DBG_IKE, " TS %R is contained in address block"
- " constraint %R", ts, block_ts);
+ " constraint %R (subset %R)", ts, block, subset);
+ list->insert_last(list, subset);
contained = TRUE;
- break;
}
}
- block_enum->destroy(block_enum);
+ enumerator->destroy(enumerator);
if (!contained)
{
DBG1(DBG_IKE, " TS %R is not contained in any"
- " address block constraint", ts);
- enumerator->destroy(enumerator);
- return FALSE;
+ " address block constraint", ts);
}
+ ts->destroy(ts);
}
- enumerator->destroy(enumerator);
+ original->destroy(original);
}
}
- return TRUE;
-}
-
-/**
- * Delete all traffic selectors in a list
- */
-static void flush_ts_list(linked_list_t *list)
-{
- traffic_selector_t *ts;
-
- while (list->remove_last(list, (void**)&ts) == SUCCESS)
- {
- ts->destroy(ts);
- }
}
METHOD(listener_t, narrow, bool,
@@ -116,13 +105,10 @@ METHOD(listener_t, narrow, bool,
switch (type)
{
case NARROW_RESPONDER:
+ case NARROW_INITIATOR_PRE_AUTH:
case NARROW_INITIATOR_POST_AUTH:
case NARROW_INITIATOR_POST_NOAUTH:
- if (!check_constraints(ike_sa, remote))
- {
- flush_ts_list(local);
- flush_ts_list(remote);
- }
+ narrow_addrblock(this, ike_sa, remote);
break;
default:
break;
diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c
index 372c978a2..d16a1170c 100644
--- a/src/libcharon/plugins/addrblock/addrblock_validator.c
+++ b/src/libcharon/plugins/addrblock/addrblock_validator.c
@@ -30,12 +30,18 @@ struct private_addrblock_validator_t {
* Public addrblock_validator_t interface.
*/
addrblock_validator_t public;
+
+ /**
+ * Whether to reject subject certificates not having a addrBlock extension
+ */
+ bool strict;
};
/**
* Do the addrblock check for two x509 plugins
*/
-static bool check_addrblock(x509_t *subject, x509_t *issuer)
+static bool check_addrblock(private_addrblock_validator_t *this,
+ x509_t *subject, x509_t *issuer)
{
bool subject_const, issuer_const, contained = TRUE;
enumerator_t *subject_enumerator, *issuer_enumerator;
@@ -51,7 +57,7 @@ static bool check_addrblock(x509_t *subject, x509_t *issuer)
if (!subject_const)
{
DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
- return FALSE;
+ return !this->strict;
}
if (!issuer_const)
{
@@ -94,7 +100,7 @@ METHOD(cert_validator_t, validate, bool,
if (subject->get_type(subject) == CERT_X509 &&
issuer->get_type(issuer) == CERT_X509)
{
- if (!check_addrblock((x509_t*)subject, (x509_t*)issuer))
+ if (!check_addrblock(this, (x509_t*)subject, (x509_t*)issuer))
{
lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_POLICY_VIOLATION,
subject);
@@ -124,6 +130,8 @@ addrblock_validator_t *addrblock_validator_create()
},
.destroy = _destroy,
},
+ .strict = lib->settings->get_bool(lib->settings,
+ "%s.plugins.addrblock.strict", TRUE, lib->ns),
);
return &this->public;
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index 3560d3634..d79c753f0 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 9d3f2f532..65cdcff94 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/attr/Makefile.in b/src/libcharon/plugins/attr/Makefile.in
index 4b900d1c0..217a42ae6 100644
--- a/src/libcharon/plugins/attr/Makefile.in
+++ b/src/libcharon/plugins/attr/Makefile.in
@@ -357,7 +357,6 @@ 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@
@@ -392,6 +391,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/attr_sql/Makefile.in b/src/libcharon/plugins/attr_sql/Makefile.in
index 077e2f3a0..668e23f07 100644
--- a/src/libcharon/plugins/attr_sql/Makefile.in
+++ b/src/libcharon/plugins/attr_sql/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/bypass_lan/Makefile.am b/src/libcharon/plugins/bypass_lan/Makefile.am
new file mode 100644
index 000000000..c1313f6ba
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-bypass-lan.la
+else
+plugin_LTLIBRARIES = libstrongswan-bypass-lan.la
+endif
+
+libstrongswan_bypass_lan_la_SOURCES = \
+ bypass_lan_plugin.h bypass_lan_plugin.c \
+ bypass_lan_listener.h bypass_lan_listener.c
+
+libstrongswan_bypass_lan_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/bypass_lan/Makefile.in b/src/libcharon/plugins/bypass_lan/Makefile.in
new file mode 100644
index 000000000..9f1dc71c9
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/Makefile.in
@@ -0,0 +1,795 @@
+# Makefile.in generated by automake 1.15 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2014 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 = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+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/bypass_lan
+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)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+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_bypass_lan_la_LIBADD =
+am_libstrongswan_bypass_lan_la_OBJECTS = bypass_lan_plugin.lo \
+ bypass_lan_listener.lo
+libstrongswan_bypass_lan_la_OBJECTS = \
+ $(am_libstrongswan_bypass_lan_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_bypass_lan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_bypass_lan_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_bypass_lan_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_bypass_lan_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_bypass_lan_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_bypass_lan_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
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ATOMICLIB = @ATOMICLIB@
+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@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+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_PACKAGE_VERSION = @PYTHON_PACKAGE_VERSION@
+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@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+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@
+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@
+p_plugins = @p_plugins@
+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@
+runstatedir = @runstatedir@
+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_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+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@
+tss2_CFLAGS = @tss2_CFLAGS@
+tss2_LIBS = @tss2_LIBS@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-bypass-lan.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-bypass-lan.la
+libstrongswan_bypass_lan_la_SOURCES = \
+ bypass_lan_plugin.h bypass_lan_plugin.c \
+ bypass_lan_listener.h bypass_lan_listener.c
+
+libstrongswan_bypass_lan_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/bypass_lan/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/bypass_lan/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-bypass-lan.la: $(libstrongswan_bypass_lan_la_OBJECTS) $(libstrongswan_bypass_lan_la_DEPENDENCIES) $(EXTRA_libstrongswan_bypass_lan_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_bypass_lan_la_LINK) $(am_libstrongswan_bypass_lan_la_rpath) $(libstrongswan_bypass_lan_la_OBJECTS) $(libstrongswan_bypass_lan_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bypass_lan_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bypass_lan_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
+
+.PRECIOUS: Makefile
+
+
+# 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/bypass_lan/bypass_lan_listener.c b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
new file mode 100644
index 000000000..e690028f2
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "bypass_lan_listener.h"
+
+#include <collections/hashtable.h>
+#include <collections/linked_list.h>
+#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
+
+#include <daemon.h>
+
+typedef struct private_bypass_lan_listener_t private_bypass_lan_listener_t;
+
+/**
+ * Private data
+ */
+struct private_bypass_lan_listener_t {
+
+ /**
+ * Public interface.
+ */
+ bypass_lan_listener_t public;
+
+ /**
+ * Currently installed bypass policies, bypass_policy_t*.
+ */
+ hashtable_t *policies;
+
+ /**
+ * Mutex to access list of policies.
+ */
+ mutex_t *mutex;
+
+ /**
+ * List of interface names to include or exclude (char*), NULL if interfaces
+ * are not filtered.
+ */
+ linked_list_t *ifaces_filter;
+
+ /**
+ * TRUE to exclude interfaces listed in ifaces_filter, FALSE to consider
+ * only those listed there.
+ */
+ bool ifaces_exclude;
+};
+
+/**
+ * Data for bypass policies
+ */
+typedef struct {
+ private_bypass_lan_listener_t *listener;
+ host_t *net;
+ uint8_t mask;
+ child_cfg_t *cfg;
+} bypass_policy_t;
+
+/**
+ * Destroy a bypass policy
+ */
+static void bypass_policy_destroy(bypass_policy_t *this)
+{
+ traffic_selector_t *ts;
+
+ if (this->cfg)
+ {
+ ts = traffic_selector_create_from_subnet(this->net->clone(this->net),
+ this->mask, 0, 0, 65535);
+ DBG1(DBG_IKE, "uninstalling bypass policy for %R", ts);
+ charon->shunts->uninstall(charon->shunts, "bypass-lan",
+ this->cfg->get_name(this->cfg));
+ this->cfg->destroy(this->cfg);
+ ts->destroy(ts);
+ }
+ this->net->destroy(this->net);
+ free(this);
+}
+
+/**
+ * Hash a bypass policy
+ */
+static u_int policy_hash(bypass_policy_t *policy)
+{
+ return chunk_hash_inc(policy->net->get_address(policy->net),
+ chunk_hash(chunk_from_thing(policy->mask)));
+}
+
+/**
+ * Compare bypass policy
+ */
+static bool policy_equals(bypass_policy_t *a, bypass_policy_t *b)
+{
+ return a->mask == b->mask && a->net->equals(a->net, b->net);
+}
+
+/**
+ * Check if an interface should be considered
+ */
+static bool consider_interface(private_bypass_lan_listener_t *this, char *iface)
+{
+ status_t expected;
+
+ if (!iface || !this->ifaces_filter)
+ {
+ return TRUE;
+ }
+ expected = this->ifaces_exclude ? NOT_FOUND : SUCCESS;
+ return this->ifaces_filter->find_first(this->ifaces_filter, (void*)streq,
+ NULL, iface) == expected;
+}
+
+/**
+ * Job updating bypass policies
+ */
+static job_requeue_t update_bypass(private_bypass_lan_listener_t *this)
+{
+ enumerator_t *enumerator;
+ hashtable_t *seen;
+ bypass_policy_t *found, *lookup;
+ host_t *net;
+ uint8_t mask;
+ char *iface;
+
+ seen = hashtable_create((hashtable_hash_t)policy_hash,
+ (hashtable_equals_t)policy_equals, 4);
+
+ this->mutex->lock(this->mutex);
+
+ enumerator = charon->kernel->create_local_subnet_enumerator(charon->kernel);
+ while (enumerator->enumerate(enumerator, &net, &mask, &iface))
+ {
+ if (!consider_interface(this, iface))
+ {
+ continue;
+ }
+
+ INIT(lookup,
+ .net = net->clone(net),
+ .mask = mask,
+ );
+ found = seen->put(seen, lookup, lookup);
+ if (found)
+ { /* in case the same subnet is on multiple interfaces */
+ bypass_policy_destroy(found);
+ }
+
+ found = this->policies->get(this->policies, lookup);
+ if (!found)
+ {
+ child_cfg_create_t child = {
+ .mode = MODE_PASS,
+ };
+ child_cfg_t *cfg;
+ traffic_selector_t *ts;
+ char name[128];
+
+ ts = traffic_selector_create_from_subnet(net->clone(net), mask,
+ 0, 0, 65535);
+ snprintf(name, sizeof(name), "Bypass LAN %R", ts);
+
+ cfg = child_cfg_create(name, &child);
+ cfg->add_traffic_selector(cfg, FALSE, ts->clone(ts));
+ cfg->add_traffic_selector(cfg, TRUE, ts);
+ charon->shunts->install(charon->shunts, "bypass-lan", cfg);
+ DBG1(DBG_IKE, "installed bypass policy for %R", ts);
+
+ INIT(found,
+ .net = net->clone(net),
+ .mask = mask,
+ .cfg = cfg,
+ );
+ this->policies->put(this->policies, found, found);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, NULL, &lookup))
+ {
+ if (!seen->get(seen, lookup))
+ {
+ this->policies->remove_at(this->policies, enumerator);
+ bypass_policy_destroy(lookup);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ seen->destroy_function(seen, (void*)bypass_policy_destroy);
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(kernel_listener_t, roam, bool,
+ private_bypass_lan_listener_t *this, bool address)
+{
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)update_bypass, this,
+ NULL, (callback_job_cancel_t)return_false));
+ return TRUE;
+}
+
+METHOD(bypass_lan_listener_t, reload_interfaces, void,
+ private_bypass_lan_listener_t *this)
+{
+ char *ifaces;
+
+ this->mutex->lock(this->mutex);
+ DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
+ this->ifaces_filter = NULL;
+ this->ifaces_exclude = FALSE;
+
+ ifaces = lib->settings->get_str(lib->settings,
+ "%s.plugins.bypass-lan.interfaces_use", NULL, lib->ns);
+ if (!ifaces)
+ {
+ this->ifaces_exclude = TRUE;
+ ifaces = lib->settings->get_str(lib->settings,
+ "%s.plugins.bypass-lan.interfaces_ignore", NULL, lib->ns);
+ }
+ if (ifaces)
+ {
+ enumerator_t *enumerator;
+ char *iface;
+
+ enumerator = enumerator_create_token(ifaces, ",", " ");
+ while (enumerator->enumerate(enumerator, &iface))
+ {
+ if (!this->ifaces_filter)
+ {
+ this->ifaces_filter = linked_list_create();
+ }
+ this->ifaces_filter->insert_last(this->ifaces_filter,
+ strdup(iface));
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->mutex->unlock(this->mutex);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)callback_job_create((callback_job_cb_t)update_bypass, this,
+ NULL, (callback_job_cancel_t)return_false));
+}
+
+METHOD(bypass_lan_listener_t, destroy, void,
+ private_bypass_lan_listener_t *this)
+{
+ enumerator_t *enumerator;
+ bypass_policy_t *policy;
+
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, NULL, &policy))
+ {
+ bypass_policy_destroy(policy);
+ }
+ enumerator->destroy(enumerator);
+ DESTROY_FUNCTION_IF(this->ifaces_filter, (void*)free);
+ this->policies->destroy(this->policies);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/*
+ * See header
+ */
+bypass_lan_listener_t *bypass_lan_listener_create()
+{
+ private_bypass_lan_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .roam = _roam,
+ },
+ .reload_interfaces = _reload_interfaces,
+ .destroy = _destroy,
+ },
+ .policies = hashtable_create((hashtable_hash_t)policy_hash,
+ (hashtable_equals_t)policy_equals, 4),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ reload_interfaces(this);
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/bypass_lan/bypass_lan_listener.h b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.h
new file mode 100644
index 000000000..737230db9
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/bypass_lan_listener.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup bypass_lan_listener bypass_lan_listener
+ * @{ @ingroup bypass_lan
+ */
+
+#ifndef BYPASS_LAN_LISTENER_H_
+#define BYPASS_LAN_LISTENER_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct bypass_lan_listener_t bypass_lan_listener_t;
+
+/**
+ * Listener to install bypass policies
+ */
+struct bypass_lan_listener_t {
+
+ /**
+ * Implements kernel_listener_t interface.
+ */
+ kernel_listener_t listener;
+
+ /**
+ * Reload ignored/used interface names from config.
+ */
+ void (*reload_interfaces)(bypass_lan_listener_t *this);
+
+ /**
+ * Destroy a bypass_lan_listener_t.
+ */
+ void (*destroy)(bypass_lan_listener_t *this);
+};
+
+/**
+ * Create a bypass_lan_listener instance.
+ */
+bypass_lan_listener_t *bypass_lan_listener_create();
+
+#endif /** BYPASS_LAN_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.c b/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.c
new file mode 100644
index 000000000..ccc05f0a7
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "bypass_lan_plugin.h"
+#include "bypass_lan_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_bypass_lan_plugin_t private_bypass_lan_plugin_t;
+
+/**
+ * Private data
+ */
+struct private_bypass_lan_plugin_t {
+
+ /**
+ * Public interface
+ */
+ bypass_lan_plugin_t public;
+
+ /**
+ * Listener installing bypass policies
+ */
+ bypass_lan_listener_t *listener;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_bypass_lan_plugin_t *this)
+{
+ return "bypass-lan";
+}
+
+/**
+ * Register listener
+ */
+static bool plugin_cb(private_bypass_lan_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *cb_data)
+{
+ if (reg)
+ {
+ charon->kernel->add_listener(charon->kernel,
+ &this->listener->listener);
+ }
+ else
+ {
+ charon->kernel->remove_listener(charon->kernel,
+ &this->listener->listener);
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_bypass_lan_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "bypass-lan"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, reload, bool,
+ private_bypass_lan_plugin_t *this)
+{
+ this->listener->reload_interfaces(this->listener);
+ return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+ private_bypass_lan_plugin_t *this)
+{
+ this->listener->destroy(this->listener);
+ free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *bypass_lan_plugin_create()
+{
+ private_bypass_lan_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .reload = _reload,
+ .destroy = _destroy,
+ },
+ },
+ .listener = bypass_lan_listener_create(),
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.h b/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.h
new file mode 100644
index 000000000..934bf0cf5
--- /dev/null
+++ b/src/libcharon/plugins/bypass_lan/bypass_lan_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup bypass_lan bypass_lan
+ * @ingroup cplugins
+ *
+ * @defgroup bypass_lan_plugin bypass_lan_plugin
+ * @{ @ingroup bypass_lan
+ */
+
+#ifndef BYPASS_LAN_PLUGIN_H_
+#define BYPASS_LAN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct bypass_lan_plugin_t bypass_lan_plugin_t;
+
+/**
+ * Plugin installing bypass policies for locally attached subnets.
+ */
+struct bypass_lan_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** BYPASS_LAN_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index 30873fa35..ffde2d7aa 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/connmark/Makefile.in b/src/libcharon/plugins/connmark/Makefile.in
index 3c9ba8036..140f1b6ad 100644
--- a/src/libcharon/plugins/connmark/Makefile.in
+++ b/src/libcharon/plugins/connmark/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/connmark/connmark_plugin.c b/src/libcharon/plugins/connmark/connmark_plugin.c
index 3f276f93e..ad44eba5f 100644
--- a/src/libcharon/plugins/connmark/connmark_plugin.c
+++ b/src/libcharon/plugins/connmark/connmark_plugin.c
@@ -90,6 +90,12 @@ plugin_t *connmark_plugin_create()
return NULL;
}
+ if (!lib->caps->keep(lib->caps, CAP_NET_RAW))
+ {
+ DBG1(DBG_NET, "connmark plugin requires CAP_NET_RAW capability");
+ return NULL;
+ }
+
INIT(this,
.public = {
.plugin = {
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index 61dd852f5..3910e4ea4 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 856ebaadf..6033c6e12 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -358,7 +358,6 @@ 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@
@@ -393,6 +392,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index fd47162c7..cd66af8c8 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 866af82be..e4b60e6ad 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -367,7 +367,6 @@ 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@
@@ -402,6 +401,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 6ff71c2a3..20c0ddb8f 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index eabe0b489..f4fb8ec42 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index e6877f75e..2dbc05f02 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_dynamic/eap_dynamic.c b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
index d0f0595de..83ccd3a8a 100644
--- a/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
+++ b/src/libcharon/plugins/eap_dynamic/eap_dynamic.c
@@ -94,6 +94,13 @@ static eap_method_t *load_method(private_eap_dynamic_t *this,
return method;
}
+METHOD(eap_method_t, get_auth, auth_cfg_t*,
+ private_eap_dynamic_t *this)
+{
+ /* get_auth() is only registered if the EAP method supports it */
+ return this->method->get_auth(this->method);
+}
+
/**
* Select the first method we can instantiate and is supported by both peers.
*/
@@ -135,6 +142,10 @@ static void select_method(private_eap_dynamic_t *this)
this->method = load_method(this, entry->type, entry->vendor);
if (this->method)
{
+ if (this->method->get_auth)
+ {
+ this->public.interface.get_auth = _get_auth;
+ }
if (entry->vendor)
{
DBG1(DBG_IKE, "vendor specific EAP method %d-%d selected",
@@ -211,6 +222,7 @@ METHOD(eap_method_t, process, status_t,
/* restart with a different method */
this->method->destroy(this->method);
this->method = NULL;
+ this->public.interface.get_auth = NULL;
return initiate(this, out);
}
if (!this->other_types)
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index a1ebc2bd0..01d509ebd 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -359,7 +359,6 @@ 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@
@@ -394,6 +393,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index e2431feda..cc1f21eed 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 2a4721814..939bbf942 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -359,7 +359,6 @@ 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@
@@ -394,6 +393,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 42c07956a..1e1936c45 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 23d9d1da8..b83a80f73 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 7d0614d46..29a2f3898 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index ba20c085e..b4abce9b3 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index 5d93852da..914c8c0be 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 8d0cd71f7..48ef92136 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -363,7 +363,6 @@ 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@
@@ -398,6 +397,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 60b7ef32b..5f12e2e2e 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -363,7 +363,6 @@ 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@
@@ -398,6 +397,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 8608587da..45e2b7498 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 4cf739e7c..8c134cff9 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index d125c13a1..a9a2dede9 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index c32671a56..cda1728c0 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index 20a3dd88e..a72b00576 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 96c6a63e5..33862f01a 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -368,7 +368,6 @@ 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@
@@ -403,6 +402,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in
index 1178d65b2..de83d83d5 100644
--- a/src/libcharon/plugins/ext_auth/Makefile.in
+++ b/src/libcharon/plugins/ext_auth/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index f37ca65db..daee657e7 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -358,7 +358,6 @@ 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@
@@ -393,6 +392,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c
index c2715bd5a..5753f7910 100644
--- a/src/libcharon/plugins/farp/farp_spoofer.c
+++ b/src/libcharon/plugins/farp/farp_spoofer.c
@@ -143,7 +143,7 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, hardware_size)),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 6, 0, 7),
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, offsetof(arp_t, protocol_size)),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 4),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 5),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3),
BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
diff --git a/src/libcharon/plugins/forecast/Makefile.in b/src/libcharon/plugins/forecast/Makefile.in
index 2f78e7749..5254bca04 100644
--- a/src/libcharon/plugins/forecast/Makefile.in
+++ b/src/libcharon/plugins/forecast/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/forecast/forecast_listener.c b/src/libcharon/plugins/forecast/forecast_listener.c
index 3f252db2d..2024c2682 100644
--- a/src/libcharon/plugins/forecast/forecast_listener.c
+++ b/src/libcharon/plugins/forecast/forecast_listener.c
@@ -212,7 +212,7 @@ static bool manage_pre_esp_in_udp(struct iptc_handle *ipth,
ADD_STRUCT(pos, struct xt_udp,
.spts = {
entry->rhost->get_port(entry->rhost),
- entry->rhost->get_port(entry->lhost)
+ entry->rhost->get_port(entry->rhost)
},
.dpts = {
entry->lhost->get_port(entry->lhost),
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index 2be7ee4a1..dd2a7a94c 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
index b20ef876a..34d6efc48 100644
--- a/src/libcharon/plugins/ha/ha_attribute.c
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -215,8 +215,12 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
if (offset == -1)
{
- DBG1(DBG_CFG, "no address left in HA pool '%s' belonging to"
- "a responsible segment", name);
+ DBG1(DBG_CFG, "no address belonging to a responsible segment left "
+ "in HA pool '%s'", name);
+ }
+ else
+ {
+ break;
}
}
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index 992ccb06c..0e83b1642 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -237,6 +237,20 @@ METHOD(listener_t, ike_rekey, bool,
return TRUE;
}
+METHOD(listener_t, alert, bool,
+ private_ha_ike_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args)
+{
+ switch (alert)
+ {
+ case ALERT_HALF_OPEN_TIMEOUT:
+ ike_updown(this, ike_sa, FALSE);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
METHOD(listener_t, ike_state_change, bool,
private_ha_ike_t *this, ike_sa_t *ike_sa, ike_sa_state_t new)
{
@@ -393,6 +407,7 @@ ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
INIT(this,
.public = {
.listener = {
+ .alert = _alert,
.ike_keys = _ike_keys,
.ike_updown = _ike_updown,
.ike_rekey = _ike_rekey,
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index 971b72cc3..025a1a25e 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
index a2c8d22c3..fb8e42ee6 100644
--- a/src/libcharon/plugins/kernel_iph/Makefile.in
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index 011ec3f5a..4d5e46033 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in
index b2df52a61..26a7090b3 100644
--- a/src/libcharon/plugins/kernel_netlink/Makefile.in
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.in
@@ -399,7 +399,6 @@ 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@
@@ -434,6 +433,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index f3846ec07..becf6b5dc 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2016 Tobias Brunner
+ * Copyright (C) 2006-2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2008-2016 Andreas Steffen
* Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
@@ -76,7 +76,7 @@
#endif
/** Base priority for installed policies */
-#define PRIO_BASE 100000
+#define PRIO_BASE 200000
/** Default lifetime of an acquire XFRM state (in seconds) */
#define DEFAULT_ACQUIRE_LIFETIME 165
@@ -117,7 +117,7 @@ struct kernel_algorithm_t {
/**
* Name of the algorithm in linux crypto API
*/
- char *name;
+ const char *name;
};
ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
@@ -221,6 +221,7 @@ static kernel_algorithm_t integrity_algs[] = {
/* {AUTH_DES_MAC, "***" }, */
/* {AUTH_KPDK_MD5, "***" }, */
{AUTH_AES_XCBC_96, "xcbc(aes)" },
+ {AUTH_AES_CMAC_96, "cmac(aes)" },
};
/**
@@ -236,7 +237,7 @@ static kernel_algorithm_t compression_algs[] = {
/**
* Look up a kernel algorithm name and its key size
*/
-static char* lookup_algorithm(transform_type_t type, int ikev2)
+static const char* lookup_algorithm(transform_type_t type, int ikev2)
{
kernel_algorithm_t *list;
int i, count;
@@ -652,14 +653,15 @@ static inline uint32_t port_mask_bits(uint16_t port_mask)
/**
* Calculate the priority of a policy
*
- * bits 0-0: restriction to network interface (0..1) 1 bit
- * bits 1-6: src + dst port mask bits (2 * 0..16) 6 bits
- * bits 7-7: restriction to protocol (0..1) 1 bit
- * bits 8-16: src + dst network mask bits (2 * 0..128) 9 bits
- * 17 bits
+ * bits 0-0: separate trap and regular policies (0..1) 1 bit
+ * bits 1-1: restriction to network interface (0..1) 1 bit
+ * bits 2-7: src + dst port mask bits (2 * 0..16) 6 bits
+ * bits 8-8: restriction to protocol (0..1) 1 bit
+ * bits 9-17: src + dst network mask bits (2 * 0..128) 9 bits
+ * 18 bits
*
- * smallest value: 000000000 0 000000 0: 0, lowest priority = 100'000
- * largest value : 100000000 1 100000 1: 65'729, highst priority = 34'271
+ * smallest value: 000000000 0 000000 0 0: 0, lowest priority = 200'000
+ * largest value : 100000000 1 100000 1 1: 131'459, highst priority = 68'541
*/
static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio,
char *interface)
@@ -672,8 +674,6 @@ static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio,
priority += PRIO_BASE;
/* fall-through to next case */
case POLICY_PRIORITY_ROUTED:
- priority += PRIO_BASE;
- /* fall-through to next case */
case POLICY_PRIORITY_DEFAULT:
priority += PRIO_BASE;
/* fall-through to next case */
@@ -684,10 +684,11 @@ static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio,
dport_mask_bits = port_mask_bits(policy->sel.dport_mask);
/* calculate priority */
- priority -= (policy->sel.prefixlen_s + policy->sel.prefixlen_d) * 256;
- priority -= policy->sel.proto ? 128 : 0;
- priority -= (sport_mask_bits + dport_mask_bits) * 2;
- priority -= (interface != NULL);
+ priority -= (policy->sel.prefixlen_s + policy->sel.prefixlen_d) * 512;
+ priority -= policy->sel.proto ? 256 : 0;
+ priority -= (sport_mask_bits + dport_mask_bits) * 4;
+ priority -= (interface != NULL) * 2;
+ priority -= (prio != POLICY_PRIORITY_ROUTED);
return priority;
}
@@ -1210,8 +1211,15 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
uint8_t protocol, uint32_t *spi)
{
- if (get_spi_internal(this, src, dst, protocol,
- 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
+ uint32_t spi_min, spi_max;
+
+ spi_min = lib->settings->get_int(lib->settings, "%s.spi_min",
+ KERNEL_SPI_MIN, lib->ns);
+ spi_max = lib->settings->get_int(lib->settings, "%s.spi_max",
+ KERNEL_SPI_MAX, lib->ns);
+
+ if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max),
+ max(spi_min, spi_max), spi) != SUCCESS)
{
DBG1(DBG_KNL, "unable to get SPI");
return FAILED;
@@ -1276,7 +1284,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
kernel_ipsec_add_sa_t *data)
{
netlink_buf_t request;
- char *alg_name, markstr[32] = "";
+ const char *alg_name;
+ char markstr[32] = "";
struct nlmsghdr *hdr;
struct xfrm_usersa_info *sa;
uint16_t icv_size = 64, ipcomp = data->ipcomp;
@@ -1367,6 +1376,11 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
default:
break;
}
+ if (id->proto == IPPROTO_AH && sa->family == AF_INET)
+ { /* use alignment to 4 bytes for IPv4 instead of the incorrect 8 byte
+ * alignment that's used by default but is only valid for IPv6 */
+ sa->flags |= XFRM_STATE_ALIGN4;
+ }
sa->reqid = data->reqid;
sa->lft.soft_byte_limit = XFRM_LIMIT(data->lifetime->bytes.rekey);
@@ -2523,7 +2537,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
{ /* we don't update the policy if the priority is lower than that of
* the currently installed one */
policy_change_done(this, policy);
- DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u,"
+ DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u, "
"refcount %d]", id->src_ts, id->dst_ts, policy_dir_names,
id->dir, markstr, cur_priority, use_count);
return SUCCESS;
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
index 0132f7269..2dc76d941 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c
@@ -476,6 +476,11 @@ struct private_kernel_netlink_net_t {
bool roam_events;
/**
+ * whether to install IPsec policy routes
+ */
+ bool install_routes;
+
+ /**
* whether to actually install virtual IPs
*/
bool install_virtual_ip;
@@ -795,6 +800,68 @@ static u_char get_scope(host_t *ip)
}
/**
+ * Determine the label of the given unicast IP address.
+ *
+ * We currently only support the default table given in RFC 6724:
+ *
+ * Prefix Precedence Label
+ * ::1/128 50 0
+ * ::/0 40 1
+ * ::ffff:0:0/96 35 4
+ * 2002::/16 30 2
+ * 2001::/32 5 5
+ * fc00::/7 3 13
+ * ::/96 1 3
+ * fec0::/10 1 11
+ * 3ffe::/16 1 12
+ */
+static u_char get_label(host_t *ip)
+{
+ struct {
+ chunk_t net;
+ u_char prefix;
+ u_char label;
+ } priorities[] = {
+ /* priority table ordered by prefix */
+ /* ::1/128 */
+ { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01), 128, 0 },
+ /* ::ffff:0:0/96 */
+ { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00), 96, 4 },
+ /* ::/96 */
+ { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 96, 3 },
+ /* 2001::/32 */
+ { chunk_from_chars(0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 32, 5 },
+ /* 2002::/16 */
+ { chunk_from_chars(0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 2 },
+ /* 3ffe::/16 */
+ { chunk_from_chars(0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 12 },
+ /* fec0::/10 */
+ { chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 10, 11 },
+ /* fc00::/7 */
+ { chunk_from_chars(0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 7, 13 },
+ };
+ int i;
+
+ for (i = 0; i < countof(priorities); i++)
+ {
+ if (host_in_subnet(ip, priorities[i].net, priorities[i].prefix))
+ {
+ return priorities[i].label;
+ }
+ }
+ /* ::/0 */
+ return 1;
+}
+
+/**
* Returns the length of the common prefix in bits up to the length of a's
* prefix, defined by RFC 6724 as the portion of the address not including the
* interface ID, which is 64-bit for most unicast addresses (see RFC 4291).
@@ -829,7 +896,7 @@ static u_char common_prefix(host_t *a, host_t *b)
static bool is_address_better(private_kernel_netlink_net_t *this,
addr_entry_t *a, addr_entry_t *b, host_t *d)
{
- u_char sa, sb, sd, pa, pb;
+ u_char sa, sb, sd, la, lb, ld, pa, pb;
/* rule 2: prefer appropriate scope */
if (d)
@@ -858,9 +925,22 @@ static bool is_address_better(private_kernel_netlink_net_t *this,
/* rule 4 is not applicable as we don't know if an address is a home or
* care-of addresses.
* rule 5 does not apply as we only compare addresses from one interface
- * rule 6 requires a policy table (optionally configurable) to match
- * configurable labels
*/
+ /* rule 6: prefer matching label */
+ if (d)
+ {
+ la = get_label(a->ip);
+ lb = get_label(b->ip);
+ ld = get_label(d);
+ if (la == ld && lb != ld)
+ {
+ return FALSE;
+ }
+ else if (lb == ld && la != ld)
+ {
+ return TRUE;
+ }
+ }
/* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */
if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY))
{
@@ -1795,12 +1875,22 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
{ /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
* as we want to ignore routes with virtual IPs we cannot use DUMP
* if these routes are not installed in a separate table */
- hdr->nlmsg_flags |= NLM_F_DUMP;
+ if (this->install_routes)
+ {
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ }
}
if (candidate)
{
chunk = candidate->get_address(candidate);
- netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
+ if (hdr->nlmsg_flags & NLM_F_DUMP)
+ {
+ netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
+ }
+ else
+ {
+ netlink_add_attribute(hdr, RTA_SRC, chunk, sizeof(request));
+ }
}
/* we use this below to match against the routes */
chunk = dest->get_address(dest);
@@ -2050,6 +2140,146 @@ METHOD(kernel_net_t, get_nexthop, host_t*,
return get_route(this, dest, prefix, TRUE, src, iface, 0);
}
+/** enumerator over subnets */
+typedef struct {
+ enumerator_t public;
+ private_kernel_netlink_net_t *private;
+ /** message from the kernel */
+ struct nlmsghdr *msg;
+ /** current message from the kernel */
+ struct nlmsghdr *current;
+ /** remaining length */
+ size_t len;
+ /** last subnet enumerated */
+ host_t *net;
+ /** interface of current net */
+ char ifname[IFNAMSIZ];
+} subnet_enumerator_t;
+
+METHOD(enumerator_t, destroy_subnet_enumerator, void,
+ subnet_enumerator_t *this)
+{
+ DESTROY_IF(this->net);
+ free(this->msg);
+ free(this);
+}
+
+METHOD(enumerator_t, enumerate_subnets, bool,
+ subnet_enumerator_t *this, host_t **net, uint8_t *mask, char **ifname)
+{
+ if (!this->current)
+ {
+ this->current = this->msg;
+ }
+ else
+ {
+ this->current = NLMSG_NEXT(this->current, this->len);
+ DESTROY_IF(this->net);
+ this->net = NULL;
+ }
+
+ while (NLMSG_OK(this->current, this->len))
+ {
+ switch (this->current->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ break;
+ case RTM_NEWROUTE:
+ {
+ struct rtmsg *msg;
+ struct rtattr *rta;
+ size_t rtasize;
+ chunk_t dst = chunk_empty;
+ uint32_t oif = 0;
+
+ msg = NLMSG_DATA(this->current);
+
+ if (!route_usable(this->current))
+ {
+ break;
+ }
+ else if (msg->rtm_table && (
+ msg->rtm_table == RT_TABLE_LOCAL ||
+ msg->rtm_table == this->private->routing_table))
+ { /* ignore our own and the local routing tables */
+ break;
+ }
+
+ rta = RTM_RTA(msg);
+ rtasize = RTM_PAYLOAD(this->current);
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case RTA_DST:
+ dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
+ case RTA_OIF:
+ if (RTA_PAYLOAD(rta) == sizeof(oif))
+ {
+ oif = *(uint32_t*)RTA_DATA(rta);
+ }
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+
+ if (dst.ptr && oif && if_indextoname(oif, this->ifname))
+ {
+ this->net = host_create_from_chunk(msg->rtm_family, dst, 0);
+ *net = this->net;
+ *mask = msg->rtm_dst_len;
+ *ifname = this->ifname;
+ return TRUE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ this->current = NLMSG_NEXT(this->current, this->len);
+ }
+ return FALSE;
+}
+
+METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
+ private_kernel_netlink_net_t *this)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out;
+ struct rtmsg *msg;
+ size_t len;
+ subnet_enumerator_t *enumerator;
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = RTM_GETROUTE;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+
+ msg = NLMSG_DATA(hdr);
+ msg->rtm_scope = RT_SCOPE_LINK;
+
+ if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
+ {
+ DBG2(DBG_KNL, "enumerating local subnets failed");
+ return enumerator_create_empty();
+ }
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_enumerate_subnets,
+ .destroy = _destroy_subnet_enumerator,
+ },
+ .private = this,
+ .msg = out,
+ .len = len,
+ );
+ return &enumerator->public;
+}
+
/**
* Manages the creation and deletion of ip addresses on an interface.
* By setting the appropriate nlmsg_type, the ip will be set or unset.
@@ -2080,16 +2310,22 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type
netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
- if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6)
- { /* if source routes are possible we let the virtual IP get deprecated
- * immediately (but mark it as valid forever) so it gets only used if
- * forced by our route, and not by the default IPv6 address selection */
- struct ifa_cacheinfo cache = {
- .ifa_valid = 0xFFFFFFFF,
- .ifa_prefered = 0,
- };
- netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
- sizeof(request));
+ if (ip->get_family(ip) == AF_INET6)
+ {
+ msg->ifa_flags |= IFA_F_NODAD;
+ if (this->rta_prefsrc_for_ipv6)
+ {
+ /* if source routes are possible we let the virtual IP get
+ * deprecated immediately (but mark it as valid forever) so it gets
+ * only used if forced by our route, and not by the default IPv6
+ * address selection */
+ struct ifa_cacheinfo cache = {
+ .ifa_valid = 0xFFFFFFFF,
+ .ifa_prefered = 0,
+ };
+ netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache),
+ sizeof(request));
+ }
}
return this->socket->send_ack(this->socket, hdr);
}
@@ -2680,6 +2916,7 @@ kernel_netlink_net_t *kernel_netlink_net_create()
.interface = {
.get_interface = _get_interface_name,
.create_address_enumerator = _create_address_enumerator,
+ .create_local_subnet_enumerator = _create_local_subnet_enumerator,
.get_source_addr = _get_source_addr,
.get_nexthop = _get_nexthop,
.add_ip = _add_ip,
@@ -2715,6 +2952,8 @@ kernel_netlink_net_t *kernel_netlink_net_create()
"%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns),
.process_route = lib->settings->get_bool(lib->settings,
"%s.process_route", TRUE, lib->ns),
+ .install_routes = lib->settings->get_bool(lib->settings,
+ "%s.install_routes", TRUE, lib->ns),
.install_virtual_ip = lib->settings->get_bool(lib->settings,
"%s.install_virtual_ip", TRUE, lib->ns),
.install_virtual_ip_on = lib->settings->get_str(lib->settings,
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
index 7165b655b..da54031a1 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -15,6 +15,29 @@
* for more details.
*/
+/*
+ * Copyright (C) 2016 secunet Security Networks AG
+ * Copyright (C) 2016 Thomas Egerer
+ *
+ * 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.
+ */
+
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
@@ -281,8 +304,9 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in,
uintptr_t seq, struct nlmsghdr **out, size_t *out_len)
{
struct nlmsghdr *hdr;
- chunk_t result = {};
entry_t *entry;
+ u_char *ptr;
+ int i;
in->nlmsg_seq = seq;
in->nlmsg_pid = getpid();
@@ -343,6 +367,14 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in,
return OUT_OF_RES;
}
+ for (i = 0, *out_len = 0; i < array_count(entry->hdrs); i++)
+ {
+ array_get(entry->hdrs, i, &hdr);
+ *out_len += hdr->nlmsg_len;
+ }
+ ptr = malloc(*out_len);
+ *out = (struct nlmsghdr*)ptr;
+
while (array_remove(entry->hdrs, ARRAY_HEAD, &hdr))
{
if (this->names)
@@ -350,14 +382,11 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in,
DBG3(DBG_KNL, "received %N %u: %b", this->names, hdr->nlmsg_type,
hdr->nlmsg_seq, hdr, hdr->nlmsg_len);
}
- result = chunk_cat("mm", result,
- chunk_create((char*)hdr, hdr->nlmsg_len));
+ memcpy(ptr, hdr, hdr->nlmsg_len);
+ ptr += hdr->nlmsg_len;
+ free(hdr);
}
destroy_entry(entry);
-
- *out_len = result.len;
- *out = (struct nlmsghdr*)result.ptr;
-
return SUCCESS;
}
@@ -557,6 +586,8 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
struct sockaddr_nl addr = {
.nl_family = AF_NETLINK,
};
+ bool force_buf = FALSE;
+ int rcvbuf_size = 0;
INIT(this,
.public = {
@@ -606,6 +637,25 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
destroy(this);
return NULL;
}
+ rcvbuf_size = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.receive_buffer_size",
+ rcvbuf_size, lib->ns);
+ if (rcvbuf_size)
+ {
+ int optname;
+
+ force_buf = lib->settings->get_bool(lib->settings,
+ "%s.plugins.kernel-netlink.force_receive_buffer_size",
+ force_buf, lib->ns);
+ optname = force_buf ? SO_RCVBUFFORCE : SO_RCVBUF;
+
+ if (setsockopt(this->socket, SOL_SOCKET, optname, &rcvbuf_size,
+ sizeof(rcvbuf_size)) == -1)
+ {
+ DBG1(DBG_KNL, "failed to %supdate receive buffer size to %d: %s",
+ force_buf ? "forcibly " : "", rcvbuf_size, strerror(errno));
+ }
+ }
if (this->parallel)
{
lib->watcher->add(lib->watcher, this->socket, WATCHER_READ, watch, this);
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in
index d00e8b337..b138a9603 100644
--- a/src/libcharon/plugins/kernel_pfkey/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 1b22ea549..17878147b 100644
--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2016 Tobias Brunner
+ * Copyright (C) 2008-2017 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -142,7 +142,7 @@
#endif
/** Base priority for installed policies */
-#define PRIO_BASE 100000
+#define PRIO_BASE 200000
#ifdef __APPLE__
/** from xnu/bsd/net/pfkeyv2.h */
@@ -597,17 +597,18 @@ static inline bool policy_entry_match_byindex(policy_entry_t *current,
* This is the same formula we use in the kernel-netlink interface, but some
* features are currently not or only partially supported by PF_KEY.
*
- * bits 0-0: reserved for interface restriction (0..1) 1 bit
- * bits 1-6: src + dst port mask bits (2 * 0..16) 6 bits
- * bits 7-7: restriction to protocol (0..1) 1 bit
- * bits 8-16: src + dst network mask bits (2 * 0..128) 9 bits
- * 17 bits
+ * bits 0-0: separate trap and regular policies (0..1) 1 bit
+ * bits 1-1: reserved for interface restriction (0..1) 1 bit
+ * bits 2-7: src + dst port mask bits (2 * 0..16) 6 bits
+ * bits 8-8: restriction to protocol (0..1) 1 bit
+ * bits 9-17: src + dst network mask bits (2 * 0..128) 9 bits
+ * 18 bits
*
- * smallest value: 000000000 0 000000 0: 0, lowest priority = 100'000
- * largest value : 100000000 1 100000 0: 65'728, highst priority = 34'272
+ * smallest value: 000000000 0 000000 0 0: 0, lowest priority = 100'000
+ * largest value : 100000000 1 100000 0 1: 131'457, highst priority = 68'543
*/
static inline uint32_t get_priority(policy_entry_t *policy,
- policy_priority_t prio)
+ policy_priority_t prio)
{
uint32_t priority = PRIO_BASE;
@@ -617,8 +618,6 @@ static inline uint32_t get_priority(policy_entry_t *policy,
priority += PRIO_BASE;
/* fall-through */
case POLICY_PRIORITY_ROUTED:
- priority += PRIO_BASE;
- /* fall-through */
case POLICY_PRIORITY_DEFAULT:
priority += PRIO_BASE;
/* fall-through */
@@ -627,10 +626,11 @@ static inline uint32_t get_priority(policy_entry_t *policy,
}
/* calculate priority */
- priority -= (policy->src.mask + policy->dst.mask) * 256;
- priority -= policy->src.proto != IPSEC_PROTO_ANY ? 128 : 0;
- priority -= policy->src.net->get_port(policy->src.net) ? 32 : 0;
- priority -= policy->dst.net->get_port(policy->dst.net) ? 32 : 0;
+ priority -= (policy->src.mask + policy->dst.mask) * 512;
+ priority -= policy->src.proto != IPSEC_PROTO_ANY ? 256 : 0;
+ priority -= policy->src.net->get_port(policy->src.net) ? 64 : 0;
+ priority -= policy->dst.net->get_port(policy->dst.net) ? 64 : 0;
+ priority -= (prio != POLICY_PRIORITY_ROUTED);
return priority;
}
@@ -1586,8 +1586,15 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
uint8_t protocol, uint32_t *spi)
{
- if (get_spi_internal(this, src, dst, protocol,
- 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS)
+ uint32_t spi_min, spi_max;
+
+ spi_min = lib->settings->get_int(lib->settings, "%s.spi_min",
+ KERNEL_SPI_MIN, lib->ns);
+ spi_max = lib->settings->get_int(lib->settings, "%s.spi_max",
+ KERNEL_SPI_MAX, lib->ns);
+
+ if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max),
+ max(spi_min, spi_max), spi) != SUCCESS)
{
DBG1(DBG_KNL, "unable to get SPI");
return FAILED;
@@ -1717,6 +1724,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa->sadb_sa_exttype = SADB_EXT_SA;
sa->sadb_sa_len = PFKEY_LEN(len);
sa->sadb_sa_spi = id->spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
if (id->proto == IPPROTO_COMP)
{
sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM,
@@ -1889,6 +1897,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
sa->sadb_sa_exttype = SADB_EXT_SA;
sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
sa->sadb_sa_spi = id->spi;
+ sa->sadb_sa_state = SADB_SASTATE_MATURE;
PFKEY_EXT_ADD(msg, sa);
/* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in
index fb1520d90..1e4b3e207 100644
--- a/src/libcharon/plugins/kernel_pfroute/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
index 236e3417f..efcf1c2a7 100644
--- a/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <ifaddrs.h>
@@ -1448,7 +1449,8 @@ static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
}
break;
case RTAX_GATEWAY:
- if (gateway)
+ if (gateway &&
+ gateway->get_family(gateway) == dst->get_family(dst))
{
add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
}
@@ -1704,6 +1706,198 @@ METHOD(kernel_net_t, get_nexthop, host_t*,
}
/**
+ * Get the number of set bits in the given netmask
+ */
+static uint8_t sockaddr_to_netmask(sockaddr_t *sockaddr, host_t *dst)
+{
+ uint8_t len = 0, i, byte, mask = 0;
+ struct sockaddr_storage ss;
+ char *addr;
+
+ /* at least some older FreeBSD versions send us shorter sockaddrs
+ * with the family set to -1 (255) */
+ if (sockaddr->sa_family == 255)
+ {
+ memset(&ss, 0, sizeof(ss));
+ memcpy(&ss, sockaddr, sockaddr->sa_len);
+ /* use the address family and length of the destination as hint */
+ ss.ss_len = *dst->get_sockaddr_len(dst);
+ ss.ss_family = dst->get_family(dst);
+ sockaddr = (sockaddr_t*)&ss;
+ }
+
+ switch (sockaddr->sa_family)
+ {
+ case AF_INET:
+ len = 4;
+ addr = (char*)&((struct sockaddr_in*)sockaddr)->sin_addr;
+ break;
+ case AF_INET6:
+ len = 16;
+ addr = (char*)&((struct sockaddr_in6*)sockaddr)->sin6_addr;
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < len; i++)
+ {
+ byte = addr[i];
+
+ if (byte == 0x00)
+ {
+ break;
+ }
+ if (byte == 0xff)
+ {
+ mask += 8;
+ }
+ else
+ {
+ while (byte & 0x80)
+ {
+ mask++;
+ byte <<= 1;
+ }
+ }
+ }
+ return mask;
+}
+
+/** enumerator over subnets */
+typedef struct {
+ enumerator_t public;
+ /** sysctl result */
+ char *buf;
+ /** length of the complete result */
+ size_t len;
+ /** start of the current route entry */
+ char *current;
+ /** last subnet enumerated */
+ host_t *net;
+ /** interface of current net */
+ char *ifname;
+} subnet_enumerator_t;
+
+METHOD(enumerator_t, destroy_subnet_enumerator, void,
+ subnet_enumerator_t *this)
+{
+ DESTROY_IF(this->net);
+ free(this->ifname);
+ free(this->buf);
+ free(this);
+}
+
+METHOD(enumerator_t, enumerate_subnets, bool,
+ subnet_enumerator_t *this, host_t **net, uint8_t *mask, char **ifname)
+{
+ enumerator_t *enumerator;
+ struct rt_msghdr *rtm;
+ struct sockaddr *addr;
+ int type;
+
+ if (!this->current)
+ {
+ this->current = this->buf;
+ }
+ else
+ {
+ rtm = (struct rt_msghdr*)this->current;
+ this->current += rtm->rtm_msglen;
+ DESTROY_IF(this->net);
+ this->net = NULL;
+ free(this->ifname);
+ this->ifname = NULL;
+ }
+
+ for (; this->current < this->buf + this->len;
+ this->current += rtm->rtm_msglen)
+ {
+ struct sockaddr *netmask;
+ uint8_t netbits = 0;
+
+ rtm = (struct rt_msghdr*)this->current;
+
+ if (rtm->rtm_version != RTM_VERSION)
+ {
+ continue;
+ }
+ if (rtm->rtm_flags & RTF_GATEWAY ||
+ rtm->rtm_flags & RTF_HOST ||
+ rtm->rtm_flags & RTF_REJECT)
+ {
+ continue;
+ }
+ enumerator = create_rtmsg_enumerator(rtm);
+ while (enumerator->enumerate(enumerator, &type, &addr))
+ {
+ if (type == RTAX_DST)
+ {
+ this->net = this->net ?: host_create_from_sockaddr(addr);
+ }
+ if (type == RTAX_NETMASK)
+ {
+ netmask = addr;
+ }
+ if (type == RTAX_IFP && addr->sa_family == AF_LINK)
+ {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl*)addr;
+ free(this->ifname);
+ this->ifname = strndup(sdl->sdl_data, sdl->sdl_nlen);
+ }
+ }
+ if (this->net)
+ {
+ netbits = sockaddr_to_netmask(netmask, this->net);
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->net && this->ifname)
+ {
+ *net = this->net;
+ *mask = netbits ?: this->net->get_address(this->net).len * 8;
+ *ifname = this->ifname;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
+ private_kernel_pfroute_net_t *this)
+{
+ subnet_enumerator_t *enumerator;
+ char *buf;
+ size_t len;
+ int mib[7] = {
+ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0, 0
+ };
+
+ if (sysctl(mib, countof(mib), NULL, &len, NULL, 0) < 0)
+ {
+ DBG2(DBG_KNL, "enumerating local subnets failed");
+ return enumerator_create_empty();
+ }
+ buf = malloc(len);
+ if (sysctl(mib, countof(mib), buf, &len, NULL, 0) < 0)
+ {
+ DBG2(DBG_KNL, "enumerating local subnets failed");
+ free(buf);
+ return enumerator_create_empty();
+ }
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_enumerate_subnets,
+ .destroy = _destroy_subnet_enumerator,
+ },
+ .buf = buf,
+ .len = len,
+ );
+ return &enumerator->public;
+}
+
+/**
* Initialize a list of local addresses.
*/
static status_t init_address_list(private_kernel_pfroute_net_t *this)
@@ -1848,6 +2042,7 @@ kernel_pfroute_net_t *kernel_pfroute_net_create()
.get_features = _get_features,
.get_interface = _get_interface_name,
.create_address_enumerator = _create_address_enumerator,
+ .create_local_subnet_enumerator = _create_local_subnet_enumerator,
.get_source_addr = _get_source_addr,
.get_nexthop = _get_nexthop,
.add_ip = _add_ip,
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
index 2adb9244b..a3368d56f 100644
--- a/src/libcharon/plugins/kernel_wfp/Makefile.in
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -368,7 +368,6 @@ 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@
@@ -403,6 +402,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
index 6ad26b72f..774fcf5c8 100644
--- a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
@@ -25,8 +25,12 @@
#include <collections/hashtable.h>
#include <processing/jobs/callback_job.h>
+#ifndef IPPROTO_IPIP
#define IPPROTO_IPIP 4
+#endif
+#ifndef IPPROTO_IPV6
#define IPPROTO_IPV6 41
+#endif
typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t;
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index 857e62961..f16304dbc 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -357,7 +357,6 @@ 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@
@@ -392,6 +391,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index f5f3df654..c6e17fb83 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -370,7 +370,6 @@ 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@
@@ -405,6 +404,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index 00258c3fa..919060469 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -366,7 +366,6 @@ 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@
@@ -401,6 +400,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index eb7efd282..4db68a3fc 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 4452739c1..78159c845 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -24,6 +24,11 @@
typedef struct private_medcli_config_t private_medcli_config_t;
/**
+ * Name of the mediation connection
+ */
+#define MEDIATION_CONN_NAME "medcli-mediation"
+
+/**
* Private data of an medcli_config_t object
*/
struct private_medcli_config_t {
@@ -72,36 +77,19 @@ static traffic_selector_t *ts_from_string(char *str)
return traffic_selector_create_dynamic(0, 0, 65535);
}
-METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
- private_medcli_config_t *this, char *name)
+/**
+ * Build a mediation config
+ */
+static peer_cfg_t *build_mediation_config(private_medcli_config_t *this,
+ peer_cfg_create_t *defaults)
{
enumerator_t *e;
- peer_cfg_t *peer_cfg, *med_cfg;
auth_cfg_t *auth;
ike_cfg_t *ike_cfg;
- child_cfg_t *child_cfg;
+ peer_cfg_t *med_cfg;
+ peer_cfg_create_t peer = *defaults;
chunk_t me, other;
- char *address, *local_net, *remote_net;
- peer_cfg_create_t peer = {
- .cert_policy = CERT_NEVER_SEND,
- .unique = UNIQUE_REPLACE,
- .keyingtries = 1,
- .rekey_time = this->rekey * 60,
- .jitter_time = this->rekey * 5,
- .over_time = this->rekey * 3,
- .dpd = this->dpd,
- .mediation = TRUE,
- };
- child_cfg_create_t child = {
- .lifetime = {
- .time = {
- .life = this->rekey * 60 + this->rekey,
- .rekey = this->rekey,
- .jitter = this->rekey
- },
- },
- .mode = MODE_TUNNEL,
- };
+ char *address;
/* query mediation server config:
* - build ike_cfg/peer_cfg for mediation connection on-the-fly
@@ -120,7 +108,9 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
- med_cfg = peer_cfg_create("mediation", ike_cfg, &peer);
+
+ peer.mediation = TRUE;
+ med_cfg = peer_cfg_create(MEDIATION_CONN_NAME, ike_cfg, &peer);
e->destroy(e);
auth = auth_cfg_create();
@@ -133,6 +123,42 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
auth->add(auth, AUTH_RULE_IDENTITY,
identification_create_from_encoding(ID_KEY_ID, other));
med_cfg->add_auth_cfg(med_cfg, auth, FALSE);
+ return med_cfg;
+}
+
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+ private_medcli_config_t *this, char *name)
+{
+ enumerator_t *e;
+ auth_cfg_t *auth;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ chunk_t me, other;
+ char *local_net, *remote_net;
+ peer_cfg_create_t peer = {
+ .cert_policy = CERT_NEVER_SEND,
+ .unique = UNIQUE_REPLACE,
+ .keyingtries = 1,
+ .rekey_time = this->rekey * 60,
+ .jitter_time = this->rekey * 5,
+ .over_time = this->rekey * 3,
+ .dpd = this->dpd,
+ };
+ child_cfg_create_t child = {
+ .lifetime = {
+ .time = {
+ .life = this->rekey * 60 + this->rekey,
+ .rekey = this->rekey,
+ .jitter = this->rekey
+ },
+ },
+ .mode = MODE_TUNNEL,
+ };
+
+ if (streq(name, "medcli-mediation"))
+ {
+ return build_mediation_config(this, &peer);
+ }
/* query mediated config:
* - use any-any ike_cfg
@@ -150,8 +176,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
DESTROY_IF(e);
return NULL;
}
- peer.mediation = FALSE;
- peer.mediated_by = med_cfg;
+ peer.mediated_by = MEDIATION_CONN_NAME;
peer.peer_id = identification_create_from_encoding(ID_KEY_ID, other);
peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index 3dd849bf0..ceb06deb1 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index 83850fcdf..ab9ece561 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/p_cscf/Makefile.in b/src/libcharon/plugins/p_cscf/Makefile.in
index 619bff10d..7b3cb2fa4 100644
--- a/src/libcharon/plugins/p_cscf/Makefile.in
+++ b/src/libcharon/plugins/p_cscf/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index 9d227a110..1fe3033dc 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -361,7 +361,6 @@ 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@
@@ -396,6 +395,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/resolve/Makefile.in
index 53af31f20..f8b62edf2 100644
--- a/src/libcharon/plugins/resolve/Makefile.in
+++ b/src/libcharon/plugins/resolve/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index d08a6f468..bf0791c42 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -358,7 +358,6 @@ 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@
@@ -393,6 +392,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index dd1da8bc5..f66ae1679 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index b6152afd7..3d07b5407 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
index ed0af93fc..692489845 100644
--- a/src/libcharon/plugins/socket_win/Makefile.in
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 0a4000e23..581225b55 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -358,7 +358,6 @@ 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@
@@ -393,6 +392,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index bbc20dca7..88cac7f26 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -381,12 +381,14 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
ike = get_ike_cfg_by_id(this, ike_cfg);
#ifdef ME
- mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by) : NULL;
+ mediated_cfg = mediated_by ? get_peer_cfg_by_id(this, mediated_by)
+ : NULL;
if (p_type)
{
peer_id = identification_create_from_encoding(p_type, p_data);
}
-#endif
+#endif /* ME */
+
if (virtual)
{
vip = host_create_from_string(virtual, 0);
@@ -405,7 +407,8 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
.dpd = dpd_delay,
#ifdef ME
.mediation = mediation,
- .mediated_by = mediated_cfg,
+ .mediated_by = mediated_cfg ?
+ mediated_cfg->get_name(mediated_cfg) : NULL,
.peer_id = peer_id,
#endif /* ME */
};
@@ -443,6 +446,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
}
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
add_child_cfgs(this, peer_cfg, id);
+ DESTROY_IF(mediated_cfg);
return peer_cfg;
}
DESTROY_IF(ike);
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 7eacc516a..50a6d5953 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -362,7 +362,6 @@ 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@
@@ -397,6 +396,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index f2d110434..bbdc2116d 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -642,28 +642,9 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
/* force unique connections for mediation connections */
msg->add_conn.unique = 1;
}
-
- if (msg->add_conn.ikeme.mediated_by)
+ else if (msg->add_conn.ikeme.mediated_by)
{
- peer_cfg_t *mediated_by;
-
- mediated_by = charon->backends->get_peer_cfg_by_name(
- charon->backends, msg->add_conn.ikeme.mediated_by);
- if (!mediated_by)
- {
- DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
- msg->add_conn.ikeme.mediated_by);
- return NULL;
- }
- if (!mediated_by->is_mediation(mediated_by))
- {
- DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is "
- "no mediation connection, aborting",
- msg->add_conn.ikeme.mediated_by, msg->add_conn.name);
- mediated_by->destroy(mediated_by);
- return NULL;
- }
- peer.mediated_by = mediated_by;
+ peer.mediated_by = msg->add_conn.ikeme.mediated_by;
if (msg->add_conn.ikeme.peerid)
{
peer.peer_id = identification_create_from_string(
@@ -982,73 +963,60 @@ static void add_ts(private_stroke_config_t *this,
stroke_end_t *end, child_cfg_t *child_cfg, bool local)
{
traffic_selector_t *ts;
+ bool ts_added = FALSE;
- if (end->tohost)
- {
- ts = traffic_selector_create_dynamic(end->protocol,
- end->from_port, end->to_port);
- child_cfg->add_traffic_selector(child_cfg, local, ts);
- }
- else
+ if (end->subnets)
{
- if (!end->subnets)
- {
- host_t *net;
+ enumerator_t *enumerator;
+ char *subnet, *pos;
+ uint16_t from_port, to_port;
+ uint8_t proto;
- net = host_create_from_string(end->address, 0);
- if (net)
- {
- ts = traffic_selector_create_from_subnet(net, 0, end->protocol,
- end->from_port, end->to_port);
- child_cfg->add_traffic_selector(child_cfg, local, ts);
- }
- }
- else
+ enumerator = enumerator_create_token(end->subnets, ",", " ");
+ while (enumerator->enumerate(enumerator, &subnet))
{
- enumerator_t *enumerator;
- char *subnet, *pos;
- uint16_t from_port, to_port;
- uint8_t proto;
+ from_port = end->from_port;
+ to_port = end->to_port;
+ proto = end->protocol;
- enumerator = enumerator_create_token(end->subnets, ",", " ");
- while (enumerator->enumerate(enumerator, &subnet))
+ pos = strchr(subnet, '[');
+ if (pos)
{
- from_port = end->from_port;
- to_port = end->to_port;
- proto = end->protocol;
-
- pos = strchr(subnet, '[');
- if (pos)
- {
- *(pos++) = '\0';
- if (!parse_protoport(pos, &from_port, &to_port, &proto))
- {
- DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
- pos);
- continue;
- }
- }
- if (streq(subnet, "%dynamic"))
+ *(pos++) = '\0';
+ if (!parse_protoport(pos, &from_port, &to_port, &proto))
{
- ts = traffic_selector_create_dynamic(proto,
- from_port, to_port);
- }
- else
- {
- ts = traffic_selector_create_from_cidr(subnet, proto,
- from_port, to_port);
- }
- if (ts)
- {
- child_cfg->add_traffic_selector(child_cfg, local, ts);
- }
- else
- {
- DBG1(DBG_CFG, "invalid subnet: %s, skipped", subnet);
+ DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
+ pos);
+ continue;
}
}
- enumerator->destroy(enumerator);
+ if (streq(subnet, "%dynamic"))
+ {
+ ts = traffic_selector_create_dynamic(proto,
+ from_port, to_port);
+ }
+ else
+ {
+ ts = traffic_selector_create_from_cidr(subnet, proto,
+ from_port, to_port);
+ }
+ if (ts)
+ {
+ child_cfg->add_traffic_selector(child_cfg, local, ts);
+ ts_added = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "invalid subnet: %s, skipped", subnet);
+ }
}
+ enumerator->destroy(enumerator);
+ }
+ if (!ts_added)
+ {
+ ts = traffic_selector_create_dynamic(end->protocol,
+ end->from_port, end->to_port);
+ child_cfg->add_traffic_selector(child_cfg, local, ts);
}
}
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index fb60d3973..ee8306772 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -641,7 +641,8 @@ static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
mode = child_cfg->get_mode(child_cfg);
if (mode == MODE_PASS || mode == MODE_DROP)
{
- if (charon->shunts->install(charon->shunts, child_cfg))
+ if (charon->shunts->install(charon->shunts,
+ peer_cfg->get_name(peer_cfg), child_cfg))
{
fprintf(out, "'%s' shunt %N policy installed\n",
name, ipsec_mode_names, mode);
@@ -729,15 +730,30 @@ METHOD(stroke_control_t, route, void,
METHOD(stroke_control_t, unroute, void,
private_stroke_control_t *this, stroke_msg_t *msg, FILE *out)
{
+ child_cfg_t *child_cfg;
child_sa_t *child_sa;
enumerator_t *enumerator;
+ char *ns, *found = NULL;
uint32_t id = 0;
- if (charon->shunts->uninstall(charon->shunts, msg->unroute.name))
+ enumerator = charon->shunts->create_enumerator(charon->shunts);
+ while (enumerator->enumerate(enumerator, &ns, &child_cfg))
{
+ if (ns && streq(msg->unroute.name, child_cfg->get_name(child_cfg)))
+ {
+ found = strdup(ns);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found && charon->shunts->uninstall(charon->shunts, found,
+ msg->unroute.name))
+ {
+ free(found);
fprintf(out, "shunt policy '%s' uninstalled\n", msg->unroute.name);
return;
}
+ free(found);
enumerator = charon->traps->create_enumerator(charon->traps);
while (enumerator->enumerate(enumerator, NULL, &child_sa))
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index 77911c7b0..9b61afb5c 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -1310,7 +1310,7 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets,
break;
}
if (match("RSA", &token) || match("ECDSA", &token) ||
- match("BLISS", &token))
+ match("BLISS", &token) || match("PKCS8", &token))
{
if (match("RSA", &token))
{
@@ -1320,10 +1320,14 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets,
{
key_type = KEY_ECDSA;
}
- else
+ else if (match("BLISS", &token))
{
key_type = KEY_BLISS;
}
+ else
+ {
+ key_type = KEY_ANY;
+ }
if (!load_private(secrets, line, line_nr, prompt, key_type))
{
break;
@@ -1356,7 +1360,7 @@ 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, BLISS, "
- "P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr);
+ "PKCS8 P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr);
break;
}
}
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index cec26579d..92e368669 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -603,7 +603,7 @@ METHOD(stroke_list_t, status, void,
/* Enumerate shunt policies */
first = TRUE;
enumerator = charon->shunts->create_enumerator(charon->shunts);
- while (enumerator->enumerate(enumerator, &child_cfg))
+ while (enumerator->enumerate(enumerator, NULL, &child_cfg))
{
if (name && !streq(name, child_cfg->get_name(child_cfg)))
{
diff --git a/src/libcharon/plugins/stroke/stroke_plugin.c b/src/libcharon/plugins/stroke/stroke_plugin.c
index f64b99f08..62095e368 100644
--- a/src/libcharon/plugins/stroke/stroke_plugin.c
+++ b/src/libcharon/plugins/stroke/stroke_plugin.c
@@ -70,6 +70,8 @@ METHOD(plugin_t, get_features, int,
PLUGIN_SDEPEND(PRIVKEY, KEY_ECDSA),
PLUGIN_SDEPEND(PRIVKEY, KEY_DSA),
PLUGIN_SDEPEND(PRIVKEY, KEY_BLISS),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_ED25519),
+ PLUGIN_SDEPEND(PRIVKEY, KEY_ED448),
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/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index e219159cc..78fd6e8d1 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 60618c051..7ec4eaad1 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -363,7 +363,6 @@ 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@
@@ -398,6 +397,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 2b6c34c33..215e3b38e 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -364,7 +364,6 @@ 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@
@@ -399,6 +398,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 2f79391f5..64b4bca24 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -358,7 +358,6 @@ 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@
@@ -393,6 +392,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index fc9bff75c..6811eb737 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -359,7 +359,6 @@ 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@
@@ -394,6 +393,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c
index 570727823..25e0756b7 100644
--- a/src/libcharon/plugins/unity/unity_handler.c
+++ b/src/libcharon/plugins/unity/unity_handler.c
@@ -235,7 +235,7 @@ static job_requeue_t add_exclude_async(entry_t *entry)
enumerator->destroy(enumerator);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
- charon->shunts->install(charon->shunts, child_cfg);
+ charon->shunts->install(charon->shunts, "unity", child_cfg);
child_cfg->destroy(child_cfg);
DBG1(DBG_IKE, "installed %N bypass policy for %R",
@@ -310,7 +310,8 @@ static bool remove_exclude(private_unity_handler_t *this, chunk_t data)
DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
ts->destroy(ts);
- success = charon->shunts->uninstall(charon->shunts, name) && success;
+ success = charon->shunts->uninstall(charon->shunts, "unity",
+ name) && success;
}
list->destroy(list);
return success;
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index a2dd067be..1a44e5566 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
index ce1520424..cdefbff79 100644
--- a/src/libcharon/plugins/vici/Makefile.in
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -456,7 +456,6 @@ 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@
@@ -491,6 +490,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index 18a3ef7b5..9bda949d0 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -1,8 +1,8 @@
# The Versatile IKE Control Interface (VICI) protocol #
-The vici plugin implements the server side of an IPC protocol to configure,
-monitor and control the IKE daemon charon. It uses request/response and event
-messages to communicate over a reliable stream based transport.
+The vici _[ˈvitʃi]_ plugin implements the server side of an IPC protocol to
+configure, monitor and control the IKE daemon charon. It uses request/response
+and event messages to communicate over a reliable stream based transport.
## Transport protocol ##
@@ -258,7 +258,7 @@ Initiates an SA while streaming _control-log_ events.
{
child = <CHILD_SA configuration name to initiate>
- ike = <optional IKE_SA configuraiton name to find child under>
+ ike = <optional IKE_SA configuration name to find child under>
timeout = <timeout in ms before returning>
init-limits = <whether limits may prevent initiating the CHILD_SA>
loglevel = <loglevel to issue "control-log" events for>
@@ -283,12 +283,29 @@ Terminates an SA while streaming _control-log_ events.
loglevel = <loglevel to issue "control-log" events for>
} => {
success = <yes or no>
+ matches = <number of matched SAs>
+ terminated = <number of terminated SAs>
errmsg = <error string on failure or timeout>
}
The default timeout of 0 waits indefinitely for a result, and a timeout value
of -1 returns a result immediately.
+### rekey() ###
+
+Initiate the rekeying of an SA.
+
+ {
+ child = <rekey a CHILD_SA by configuration name>
+ ike = <rekey an IKE_SA by configuration name>
+ child-id = <rekey a CHILD_SA by its reqid>
+ ike-id = <rekey an IKE_SA by its unique id>
+ } => {
+ success = <yes or no>
+ matches = <number of matched SAs>
+ errmsg = <error string on failure>
+ }
+
### redirect() ###
Redirect a client-initiated IKE_SA to another gateway. Only for IKEv2 and if
@@ -303,6 +320,7 @@ supported by the peer.
wildcards>
} => {
success = <yes or no>
+ matches = <number of matched SAs>
errmsg = <error string on failure>
}
@@ -312,7 +330,7 @@ Install a trap, drop or bypass policy defined by a CHILD_SA config.
{
child = <CHILD_SA configuration name to install>
- ike = <optional IKE_SA configuraiton name to find child under>
+ ike = <optional IKE_SA configuration name to find child under>
} => {
success = <yes or no>
errmsg = <error string on failure>
@@ -324,6 +342,8 @@ Uninstall a trap, drop or bypass policy defined by a CHILD_SA config.
{
child = <CHILD_SA configuration name to install>
+ ike = <optional IKE_SA configuration name to find child under,
+ if not given the first policy matching child is removed>
} => {
success = <yes or no>
errmsg = <error string on failure>
@@ -352,6 +372,7 @@ _list-policy_ events.
pass = <set to yes to list bypass policies>
trap = <set to yes to list trap policies>
child = <filter by CHILD_SA configuration name>
+ ike = <filter by IKE_SA configuration name>
} => {
# completes after streaming list-sa events
}
@@ -466,12 +487,53 @@ Load a private key into the daemon.
errmsg = <error string on failure>
}
+### unload-key() ###
+
+Unload the private key with the given key identifier.
+
+ {
+ id = <hex-encoded SHA-1 key identifier of the private key to unload>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### get-keys() ###
+
+Return a list of identifiers of private keys loaded exclusively over vici, not
+including keys found in other backends.
+
+ {} => {
+ keys = [
+ <list of hex-encoded SHA-1 key identifiers>
+ ]
+ }
+
+### load-token() ###
+
+Load a private key located on a token into the daemon. Such keys may be listed
+and unloaded using the _get-keys_ and _unload-key_ commands, respectively (based
+on the key identifier derived from the public key).
+
+ {
+ handle = <hex-encoded CKA_ID of the private key on token>
+ slot = <optional slot number>
+ module = <optional PKCS#11 module>
+ pin = <optional PIN to access the key, has to be provided via other
+ means if not given>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ id = <hex-encoded SHA-1 key identifier of the public key on success>
+ }
+
### load-shared() ###
Load a shared IKE PSK, EAP or XAuth secret into the daemon.
{
- type = <private key type, IKE|EAP|XAUTH>
+ id = <optional unique identifier of this shared key>
+ type = <shared key type, IKE|EAP|XAUTH>
data = <raw shared key data>
owners = [
<list of shared key owner identities>
@@ -481,6 +543,29 @@ Load a shared IKE PSK, EAP or XAuth secret into the daemon.
errmsg = <error string on failure>
}
+### unload-shared() ###
+
+Unload a previously loaded shared IKE PSK, EAP or XAuth secret by its unique
+identifier.
+
+ {
+ id = <unique identifier of the shared key to unload>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### get-shared() ###
+
+Return a list of unique identifiers of shared keys loaded exclusively over vici,
+not including keys found in other backends.
+
+ {} => {
+ keys = [
+ <list of unique identifiers>
+ ]
+ }
+
### flush-certs() ###
Flushes the certificate cache. The optional type argument allows to flush
@@ -569,6 +654,7 @@ List the currently loaded pools.
{
leases = <set to yes to include leases>
+ name = <optional name of the pool to query>
} => {
<pool name>* = {
base = <virtual IP pool base address>
@@ -678,7 +764,8 @@ command.
<list of tasks currently handling passively>
]
child-sas = {
- <child-sa-name>* = {
+ <unique child-sa-name>* = {
+ name = <name of the CHILD_SA>
uniqueid = <unique CHILD_SA identifier>
reqid = <reqid of CHILD_SA>
state = <state string of CHILD_SA>
@@ -689,6 +776,10 @@ command.
spi-out = <hex encoded outbound SPI>
cpi-in = <hex encoded inbound CPI, if using compression>
cpi-out = <hex encoded outbound CPI, if using compression>
+ mark-in = <hex encoded inbound Netfilter mark value>
+ mark-mask-in = <hex encoded inbound Netfilter mark mask>
+ mark-out = <hex encoded outbound Netfilter mark value>
+ mark-mask-out = <hex encoded outbound Netfilter mark mask>
encr-alg = <ESP encryption algorithm name, if any>
encr-keysize = <ESP encryption key size, if applicable>
integ-alg = <ESP or AH integrity algorithm name, if any>
@@ -722,7 +813,9 @@ The _list-policy_ event is issued to stream installed policies during an active
_list-policies_ command.
{
- <child-sa-config-name> = {
+ <ike-sa-config-name/child-sa-config-name> = {
+ child = <CHILD_SA configuration name>
+ ike = <IKE_SA configuration name or namespace, if available>
mode = <policy mode, tunnel|transport|pass|drop>
local-ts = [
<list of local traffic selectors>
diff --git a/src/libcharon/plugins/vici/perl/Makefile.in b/src/libcharon/plugins/vici/perl/Makefile.in
index 523868c68..385aa9775 100644
--- a/src/libcharon/plugins/vici/perl/Makefile.in
+++ b/src/libcharon/plugins/vici/perl/Makefile.in
@@ -274,7 +274,6 @@ 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@
@@ -309,6 +308,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in
index 4f1a91703..f783d7068 100644
--- a/src/libcharon/plugins/vici/python/Makefile.in
+++ b/src/libcharon/plugins/vici/python/Makefile.in
@@ -296,7 +296,6 @@ 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@
@@ -331,6 +330,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/vici/python/vici/protocol.py b/src/libcharon/plugins/vici/python/vici/protocol.py
index 4951817eb..919231d43 100644
--- a/src/libcharon/plugins/vici/python/vici/protocol.py
+++ b/src/libcharon/plugins/vici/python/vici/protocol.py
@@ -33,7 +33,10 @@ class Transport(object):
"""Ensure to read count bytes from the socket"""
data = b""
while len(data) < count:
- data += self.socket.recv(count - len(data))
+ buf = self.socket.recv(count - len(data))
+ if not buf:
+ raise socket.error('Connection closed')
+ data += buf
return data
@@ -59,7 +62,7 @@ class Packet(object):
@classmethod
def _named_request(cls, request_type, request, message=None):
- request = request.encode()
+ requestdata = request.encode("UTF-8")
payload = struct.pack("!BB", request_type, len(request)) + request
if message is not None:
return payload + message
@@ -102,12 +105,12 @@ class Message(object):
@classmethod
def serialize(cls, message):
def encode_named_type(marker, name):
- name = name.encode()
+ name = name.encode("UTF-8")
return struct.pack("!BB", marker, len(name)) + name
def encode_blob(value):
if not isinstance(value, bytes):
- value = str(value).encode()
+ value = str(value).encode("UTF-8")
return struct.pack("!H", len(value)) + value
def serialize_list(lst):
@@ -144,7 +147,7 @@ class Message(object):
def deserialize(cls, stream):
def decode_named_type(stream):
length, = struct.unpack("!B", stream.read(1))
- return stream.read(length).decode()
+ return stream.read(length).decode("UTF-8")
def decode_blob(stream):
length, = struct.unpack("!H", stream.read(2))
diff --git a/src/libcharon/plugins/vici/python/vici/session.py b/src/libcharon/plugins/vici/python/vici/session.py
index 5bd4b7c40..1383fa778 100644
--- a/src/libcharon/plugins/vici/python/vici/session.py
+++ b/src/libcharon/plugins/vici/python/vici/session.py
@@ -208,13 +208,15 @@ class Session(object):
"""
self.handler.request("unload-pool", pool_name)
- def get_pools(self):
+ def get_pools(self, options):
"""Retrieve loaded pools.
+ :param options: filter by name and/or retrieve leases (optional)
+ :type options: dict
:return: loaded pools
:rtype: dict
"""
- return self.handler.request("get-pools")
+ return self.handler.request("get-pools", options)
def listen(self, event_types):
"""Register and listen for the given events.
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
index e176285a8..125f44ee1 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.in
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -274,7 +274,6 @@ 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@
@@ -309,6 +308,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb
index 1a95fc3dd..bcf1a17be 100644
--- a/src/libcharon/plugins/vici/ruby/lib/vici.rb
+++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb
@@ -492,8 +492,8 @@ module Vici
##
# Get the currently loaded pools.
- def get_pools()
- @transp.request("get-pools").root
+ def get_pools(options)
+ @transp.request("get-pools", Message.new(options)).root
end
##
diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c
index e0d9b4ae8..4e1fa9708 100644
--- a/src/libcharon/plugins/vici/vici_attribute.c
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2014-2015 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2014-2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
@@ -668,10 +668,11 @@ CALLBACK(get_pools, vici_message_t*,
identification_t *uid;
host_t *lease;
bool list_leases, on;
- char buf[32];
+ char buf[32], *filter;
int i;
list_leases = message->get_bool(message, FALSE, "leases");
+ filter = message->get_str(message, NULL, "name");
builder = vici_builder_create();
@@ -679,6 +680,11 @@ CALLBACK(get_pools, vici_message_t*,
enumerator = this->pools->create_enumerator(this->pools);
while (enumerator->enumerate(enumerator, &name, &pool))
{
+ if (filter && !streq(name, filter))
+ {
+ continue;
+ }
+
vips = pool->vips;
builder->begin_section(builder, name);
diff --git a/src/libcharon/plugins/vici/vici_authority.c b/src/libcharon/plugins/vici/vici_authority.c
index 94a7f68f6..0fa158b32 100644
--- a/src/libcharon/plugins/vici/vici_authority.c
+++ b/src/libcharon/plugins/vici/vici_authority.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -199,9 +200,28 @@ typedef struct {
typedef struct {
request_data_t *request;
authority_t *authority;
+ char *handle;
+ uint32_t slot;
+ char *module;
+ char *file;
} load_data_t;
/**
+ * Clean up data associated with an authority load
+ */
+static void free_load_data(load_data_t *data)
+{
+ if (data->authority)
+ {
+ authority_destroy(data->authority);
+ }
+ free(data->handle);
+ free(data->module);
+ free(data->file);
+ free(data);
+}
+
+/**
* Parse a string
*/
CALLBACK(parse_string, bool,
@@ -217,6 +237,28 @@ CALLBACK(parse_string, bool,
}
/**
+ * Parse a uint32_t
+ */
+CALLBACK(parse_uint32, bool,
+ uint32_t *out, chunk_t v)
+{
+ char buf[16], *end;
+ u_long l;
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ l = strtoul(buf, &end, 0);
+ if (*end == 0)
+ {
+ *out = l;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Parse list of URIs
*/
CALLBACK(parse_uris, bool,
@@ -266,8 +308,12 @@ CALLBACK(authority_kv, bool,
load_data_t *data, vici_message_t *message, char *name, chunk_t value)
{
parse_rule_t rules[] = {
- { "cacert", parse_cacert, &data->authority->cert },
- { "cert_uri_base", parse_string, &data->authority->cert_uri_base },
+ { "cacert", parse_cacert, &data->authority->cert },
+ { "file", parse_string, &data->file },
+ { "handle", parse_string, &data->handle },
+ { "slot", parse_uint32, &data->slot },
+ { "module", parse_string, &data->module },
+ { "cert_uri_base", parse_string, &data->authority->cert_uri_base },
};
return parse_rules(rules, countof(rules), name, value,
@@ -341,21 +387,60 @@ CALLBACK(authority_sn, bool,
linked_list_t *authorities;
authority_t *authority;
vici_cred_t *cred;
+ load_data_t *data;
+ chunk_t handle;
- load_data_t data = {
+ INIT(data,
.request = request,
.authority = authority_create(name),
- };
+ .slot = -1,
+ );
DBG2(DBG_CFG, " authority %s:", name);
- if (!message->parse(message, ctx, NULL, authority_kv, authority_li, &data) ||
- !data.authority->cert)
+ if (!message->parse(message, ctx, NULL, authority_kv, authority_li, data))
+ {
+ free_load_data(data);
+ return FALSE;
+ }
+ if (!data->authority->cert)
+ {
+ if (data->file)
+ {
+ data->authority->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, data->file, BUILD_END);
+ }
+ else if (data->handle)
+ {
+ handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
+ if (data->slot != -1)
+ {
+ data->authority->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_PKCS11_KEYID, handle,
+ BUILD_PKCS11_SLOT, data->slot,
+ data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+ data->module, BUILD_END);
+ }
+ else
+ {
+ data->authority->cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_PKCS11_KEYID, handle,
+ data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+ data->module, BUILD_END);
+ }
+ chunk_free(&handle);
+ }
+ }
+ if (!data->authority->cert)
{
- authority_destroy(data.authority);
+ request->reply = create_reply("CA certificate missing: %s", name);
+ free_load_data(data);
return FALSE;
}
- log_authority_data(data.authority);
+ log_authority_data(data->authority);
request->this->lock->write_lock(request->this->lock);
@@ -372,12 +457,14 @@ CALLBACK(authority_sn, bool,
}
}
enumerator->destroy(enumerator);
- authorities->insert_last(authorities, data.authority);
+ authorities->insert_last(authorities, data->authority);
cred = request->this->cred;
- data.authority->cert = cred->add_cert(cred, data.authority->cert);
+ data->authority->cert = cred->add_cert(cred, data->authority->cert);
+ data->authority = NULL;
request->this->lock->unlock(request->this->lock);
+ free_load_data(data);
return TRUE;
}
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index 2110fd31d..12497ec5e 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -2,7 +2,7 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
- * Copyright (C) 2015-2016 Tobias Brunner
+ * Copyright (C) 2015-2017 Tobias Brunner
* Copyright (C) 2015-2016 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -247,6 +247,28 @@ typedef struct {
} request_data_t;
/**
+ * Certificate data
+ */
+typedef struct {
+ request_data_t *request;
+ char *handle;
+ uint32_t slot;
+ char *module;
+ char *file;
+} cert_data_t;
+
+/**
+ * Clean up certificate data
+ */
+static void free_cert_data(cert_data_t *data)
+{
+ free(data->handle);
+ free(data->module);
+ free(data->file);
+ free(data);
+}
+
+/**
* Auth config data
*/
typedef struct {
@@ -295,6 +317,12 @@ typedef struct {
uint64_t rekey_time;
uint64_t over_time;
uint64_t rand_time;
+ uint8_t dscp;
+#ifdef ME
+ bool mediation;
+ char *mediated_by;
+ identification_t *peer_id;
+#endif /* ME */
} peer_data_t;
/**
@@ -370,6 +398,7 @@ static void log_peer_data(peer_data_t *data)
DBG2(DBG_CFG, " send_cert = %N", cert_policy_names, data->send_cert);
DBG2(DBG_CFG, " mobike = %u", data->mobike);
DBG2(DBG_CFG, " aggressive = %u", data->aggressive);
+ DBG2(DBG_CFG, " dscp = 0x%.2x", data->dscp);
DBG2(DBG_CFG, " encap = %u", data->encap);
DBG2(DBG_CFG, " dpd_delay = %llu", data->dpd_delay);
DBG2(DBG_CFG, " dpd_timeout = %llu", data->dpd_timeout);
@@ -381,6 +410,14 @@ static void log_peer_data(peer_data_t *data)
DBG2(DBG_CFG, " over_time = %llu", data->over_time);
DBG2(DBG_CFG, " rand_time = %llu", data->rand_time);
DBG2(DBG_CFG, " proposals = %#P", data->proposals);
+#ifdef ME
+ DBG2(DBG_CFG, " mediation = %u", data->mediation);
+ if (data->mediated_by)
+ {
+ DBG2(DBG_CFG, " mediated_by = %s", data->mediated_by);
+ DBG2(DBG_CFG, " mediation_peer = %Y", data->peer_id);
+ }
+#endif /* ME */
if (data->vips->get_count(data->vips))
{
@@ -425,6 +462,10 @@ static void free_peer_data(peer_data_t *data)
free(data->pools);
free(data->local_addrs);
free(data->remote_addrs);
+#ifdef ME
+ free(data->mediated_by);
+ DESTROY_IF(data->peer_id);
+#endif /* ME */
}
/**
@@ -461,7 +502,8 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " updown = %s", cfg->updown);
DBG2(DBG_CFG, " hostaccess = %u", cfg->hostaccess);
DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp);
- DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, cfg->mode);
+ DBG2(DBG_CFG, " mode = %N%s", ipsec_mode_names, cfg->mode,
+ cfg->proxy_mode ? "_PROXY" : "");
DBG2(DBG_CFG, " policies = %u", data->policies);
DBG2(DBG_CFG, " policies_fwd_out = %u", data->policies_fwd_out);
if (data->replay_window != REPLAY_UNDEFINED)
@@ -770,20 +812,22 @@ CALLBACK(parse_bool, bool,
* Parse a ipsec_mode_t
*/
CALLBACK(parse_mode, bool,
- ipsec_mode_t *out, chunk_t v)
+ child_cfg_create_t *cfg, chunk_t v)
{
enum_map_t map[] = {
- { "tunnel", MODE_TUNNEL },
- { "transport", MODE_TRANSPORT },
- { "beet", MODE_BEET },
- { "drop", MODE_DROP },
- { "pass", MODE_PASS },
+ { "tunnel", MODE_TUNNEL },
+ { "transport", MODE_TRANSPORT },
+ { "transport_proxy", MODE_TRANSPORT },
+ { "beet", MODE_BEET },
+ { "drop", MODE_DROP },
+ { "pass", MODE_PASS },
};
int d;
if (parse_map(map, countof(map), &d, v))
{
- *out = d;
+ cfg->mode = d;
+ cfg->proxy_mode = (d == MODE_TRANSPORT) && (v.len > 9);
return TRUE;
}
return FALSE;
@@ -814,10 +858,9 @@ CALLBACK(parse_action, bool,
}
/**
- * Parse a uint32_t
+ * Parse a uint32_t with the given base
*/
-CALLBACK(parse_uint32, bool,
- uint32_t *out, chunk_t v)
+static bool parse_uint32_base(uint32_t *out, chunk_t v, int base)
{
char buf[16], *end;
u_long l;
@@ -826,7 +869,7 @@ CALLBACK(parse_uint32, bool,
{
return FALSE;
}
- l = strtoul(buf, &end, 0);
+ l = strtoul(buf, &end, base);
if (*end == 0)
{
*out = l;
@@ -836,6 +879,24 @@ CALLBACK(parse_uint32, bool,
}
/**
+ * Parse a uint32_t
+ */
+CALLBACK(parse_uint32, bool,
+ uint32_t *out, chunk_t v)
+{
+ return parse_uint32_base(out, v, 0);
+}
+
+/**
+ * Parse a uint32_t in binary encoding
+ */
+CALLBACK(parse_uint32_bin, bool,
+ uint32_t *out, chunk_t v)
+{
+ return parse_uint32_base(out, v, 2);
+}
+
+/**
* Parse a uint64_t
*/
CALLBACK(parse_uint64, bool,
@@ -984,6 +1045,20 @@ CALLBACK(parse_tfc, bool,
}
/**
+ * Parse 6-bit DSCP value
+ */
+CALLBACK(parse_dscp, bool,
+ uint8_t *out, chunk_t v)
+{
+ if (parse_uint32_bin(out, v))
+ {
+ *out = *out & 0x3f;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Parse authentication config
*/
CALLBACK(parse_auth, bool,
@@ -1109,27 +1184,52 @@ CALLBACK(parse_group, bool,
}
/**
- * Parse a certificate; add as auth rule to config
+ * Parse certificate policy
*/
-static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
+CALLBACK(parse_cert_policy, bool,
+ auth_cfg_t *cfg, chunk_t v)
+{
+ char buf[BUF_LEN];
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(buf));
+ return TRUE;
+}
+
+/**
+ * Add a certificate as auth rule to config
+ */
+static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert)
{
vici_authority_t *authority;
vici_cred_t *cred;
+
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ authority = auth->request->this->authority;
+ authority->check_for_hash_and_url(authority, cert);
+ }
+ cred = auth->request->this->cred;
+ cert = cred->add_cert(cred, cert);
+ auth->cfg->add(auth->cfg, rule, cert);
+ return TRUE;
+}
+
+/**
+ * Parse a certificate; add as auth rule to config
+ */
+static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
+{
certificate_t *cert;
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_PEM, v, BUILD_END);
if (cert)
{
- if (rule == AUTH_RULE_SUBJECT_CERT)
- {
- authority = auth->request->this->authority;
- authority->check_for_hash_and_url(authority, cert);
- }
- cred = auth->request->this->cred;
- cert = cred->add_cert(cred, cert);
- auth->cfg->add(auth->cfg, rule, cert);
- return TRUE;
+ return add_cert(auth, rule, cert);
}
return FALSE;
}
@@ -1314,6 +1414,38 @@ CALLBACK(parse_hosts, bool,
return TRUE;
}
+#ifdef ME
+/**
+ * Parse peer ID
+ */
+CALLBACK(parse_peer_id, bool,
+ identification_t **out, chunk_t v)
+{
+ char buf[BUF_LEN];
+
+ if (!vici_stringify(v, buf, sizeof(buf)))
+ {
+ return FALSE;
+ }
+ *out = identification_create_from_string(buf);
+ return TRUE;
+}
+#endif /* ME */
+
+CALLBACK(cert_kv, bool,
+ cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "handle", parse_string, &cert->handle },
+ { "slot", parse_uint32, &cert->slot },
+ { "module", parse_string, &cert->module },
+ { "file", parse_string, &cert->file },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &cert->request->reply);
+}
+
CALLBACK(child_li, bool,
child_data_t *child, vici_message_t *message, char *name, chunk_t value)
{
@@ -1334,7 +1466,7 @@ CALLBACK(child_kv, bool,
parse_rule_t rules[] = {
{ "updown", parse_string, &child->cfg.updown },
{ "hostaccess", parse_bool, &child->cfg.hostaccess },
- { "mode", parse_mode, &child->cfg.mode },
+ { "mode", parse_mode, &child->cfg },
{ "policies", parse_bool, &child->policies },
{ "policies_fwd_out", parse_bool, &child->policies_fwd_out },
{ "replay_window", parse_uint32, &child->replay_window },
@@ -1369,6 +1501,7 @@ CALLBACK(auth_li, bool,
{
parse_rule_t rules[] = {
{ "groups", parse_group, auth->cfg },
+ { "cert_policy", parse_cert_policy, auth },
{ "certs", parse_certs, auth },
{ "cacerts", parse_cacerts, auth },
{ "pubkeys", parse_pubkeys, auth },
@@ -1417,6 +1550,7 @@ CALLBACK(peer_kv, bool,
{ "version", parse_uint32, &peer->version },
{ "aggressive", parse_bool, &peer->aggressive },
{ "pull", parse_bool, &peer->pull },
+ { "dscp", parse_dscp, &peer->dscp },
{ "encap", parse_bool, &peer->encap },
{ "mobike", parse_bool, &peer->mobike },
{ "dpd_delay", parse_time, &peer->dpd_delay },
@@ -1432,12 +1566,94 @@ CALLBACK(peer_kv, bool,
{ "rekey_time", parse_time, &peer->rekey_time },
{ "over_time", parse_time, &peer->over_time },
{ "rand_time", parse_time, &peer->rand_time },
+#ifdef ME
+ { "mediation", parse_bool, &peer->mediation },
+ { "mediated_by", parse_string, &peer->mediated_by },
+ { "mediation_peer", parse_peer_id, &peer->peer_id },
+#endif /* ME */
};
return parse_rules(rules, countof(rules), name, value,
&peer->request->reply);
}
+CALLBACK(auth_sn, bool,
+ auth_data_t *auth, vici_message_t *message, vici_parse_context_t *ctx,
+ char *name)
+{
+ if (strcasepfx(name, "cert") ||
+ strcasepfx(name, "cacert"))
+ {
+ cert_data_t *data;
+ auth_rule_t rule;
+ certificate_t *cert;
+ chunk_t handle;
+
+ INIT(data,
+ .request = auth->request,
+ .slot = -1,
+ );
+
+ if (!message->parse(message, ctx, NULL, cert_kv, NULL, data))
+ {
+ free_cert_data(data);
+ return FALSE;
+ }
+ if (!data->handle && !data->file)
+ {
+ auth->request->reply = create_reply("handle or file path missing: "
+ "%s", name);
+ free_cert_data(data);
+ return FALSE;
+ }
+ else if (data->handle && data->file)
+ {
+ auth->request->reply = create_reply("handle and file path given: "
+ "%s", name);
+ free_cert_data(data);
+ return FALSE;
+ }
+
+ if (data->file)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, data->file, BUILD_END);
+ }
+ else
+ {
+ handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
+ if (data->slot != -1)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_PKCS11_KEYID, handle,
+ BUILD_PKCS11_SLOT, data->slot,
+ data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+ data->module, BUILD_END);
+ }
+ else
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_X509, BUILD_PKCS11_KEYID, handle,
+ data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+ data->module, BUILD_END);
+ }
+ chunk_free(&handle);
+ }
+ free_cert_data(data);
+ if (!cert)
+ {
+ auth->request->reply = create_reply("unable to load certificate: "
+ "%s", name);
+ return FALSE;
+ }
+ rule = strcasepfx(name, "cert") ? AUTH_RULE_SUBJECT_CERT
+ : AUTH_RULE_CA_CERT;
+ return add_cert(auth, rule, cert);
+ }
+ auth->request->reply = create_reply("invalid section: %s", name);
+ return FALSE;
+}
+
/**
* Check and update lifetimes
*/
@@ -1600,7 +1816,7 @@ CALLBACK(peer_sn, bool,
.cfg = auth_cfg_create(),
);
- if (!message->parse(message, ctx, NULL, auth_kv, auth_li, auth))
+ if (!message->parse(message, ctx, auth_sn, auth_kv, auth_li, auth))
{
free_auth_data(auth);
return FALSE;
@@ -1703,7 +1919,8 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
{
case MODE_PASS:
case MODE_DROP:
- charon->shunts->install(charon->shunts, child_cfg);
+ charon->shunts->install(charon->shunts,
+ peer_cfg->get_name(peer_cfg), child_cfg);
break;
default:
charon->traps->install(charon->traps, peer_cfg, child_cfg,
@@ -1724,6 +1941,7 @@ static void clear_start_action(private_vici_config_t *this, char *peer_name,
{
enumerator_t *enumerator, *children;
child_sa_t *child_sa;
+ peer_cfg_t *peer_cfg;
ike_sa_t *ike_sa;
uint32_t id = 0, others;
array_t *ids = NULL, *ikeids = NULL;
@@ -1811,13 +2029,15 @@ static void clear_start_action(private_vici_config_t *this, char *peer_name,
{
case MODE_PASS:
case MODE_DROP:
- charon->shunts->uninstall(charon->shunts, name);
+ charon->shunts->uninstall(charon->shunts, peer_name, name);
break;
default:
enumerator = charon->traps->create_enumerator(charon->traps);
- while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ while (enumerator->enumerate(enumerator, &peer_cfg,
+ &child_sa))
{
- if (streq(name, child_sa->get_name(child_sa)))
+ if (streq(peer_name, peer_cfg->get_name(peer_cfg)) &&
+ streq(name, child_sa->get_name(child_sa)))
{
id = child_sa->get_reqid(child_sa);
break;
@@ -2080,12 +2300,48 @@ CALLBACK(config_sn, bool,
peer.rand_time = min(peer.over_time, peer.rand_time / 2);
}
+#ifdef ME
+ if (peer.mediation && peer.mediated_by)
+ {
+ DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
+ "at the same time, config discarded");
+ free_peer_data(&peer);
+ return FALSE;
+ }
+ if (peer.mediation)
+ { /* force unique connections for mediation connections */
+ peer.unique = UNIQUE_REPLACE;
+ }
+ else if (peer.mediated_by)
+ { /* fallback to remote identity of first auth round if peer_id is not
+ * given explicitly */
+ auth_cfg_t *cfg;
+
+ if (!peer.peer_id &&
+ peer.remote->get_first(peer.remote, (void**)&cfg) == SUCCESS)
+ {
+ peer.peer_id = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (peer.peer_id)
+ {
+ peer.peer_id = peer.peer_id->clone(peer.peer_id);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "mediation peer missing for mediated connection, "
+ "config discarded");
+ free_peer_data(&peer);
+ return FALSE;
+ }
+ }
+ }
+#endif /* ME */
+
log_peer_data(&peer);
ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
peer.local_addrs, peer.local_port,
peer.remote_addrs, peer.remote_port,
- peer.fragmentation, 0);
+ peer.fragmentation, peer.dscp);
cfg = (peer_cfg_create_t){
.cert_policy = peer.send_cert,
@@ -2101,6 +2357,14 @@ CALLBACK(config_sn, bool,
.dpd = peer.dpd_delay,
.dpd_timeout = peer.dpd_timeout,
};
+#ifdef ME
+ cfg.mediation = peer.mediation;
+ if (peer.mediated_by)
+ {
+ cfg.mediated_by = peer.mediated_by;
+ cfg.peer_id = peer.peer_id->clone(peer.peer_id);
+ }
+#endif /* ME */
peer_cfg = peer_cfg_create(name, ike_cfg, &cfg);
while (peer.local->remove_first(peer.local,
diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h
index 0c237e7de..6bff41c31 100644
--- a/src/libcharon/plugins/vici/vici_config.h
+++ b/src/libcharon/plugins/vici/vici_config.h
@@ -38,7 +38,7 @@ typedef struct vici_config_t vici_config_t;
struct vici_config_t {
/**
- * Implements a configuraiton backend.
+ * Implements a configuration backend.
*/
backend_t backend;
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 44003819a..afee649f7 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2015 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2015-2017 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
@@ -23,6 +23,8 @@
#include <daemon.h>
#include <collections/array.h>
+#include <processing/jobs/rekey_ike_sa_job.h>
+#include <processing/jobs/rekey_child_sa_job.h>
#include <processing/jobs/redirect_job.h>
typedef struct private_vici_control_t private_vici_control_t;
@@ -360,6 +362,100 @@ CALLBACK(terminate, vici_message_t*,
return builder->finalize(builder);
}
+CALLBACK(rekey, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *isas, *csas;
+ char *child, *ike, *errmsg = NULL;
+ u_int child_id, ike_id, found = 0;
+ ike_sa_t *ike_sa;
+ child_sa_t *child_sa;
+ vici_builder_t *builder;
+
+ child = request->get_str(request, NULL, "child");
+ ike = request->get_str(request, NULL, "ike");
+ child_id = request->get_int(request, 0, "child-id");
+ ike_id = request->get_int(request, 0, "ike-id");
+
+ if (!child && !ike && !ike_id && !child_id)
+ {
+ return send_reply(this, "missing rekey selector");
+ }
+
+ if (ike_id)
+ {
+ DBG1(DBG_CFG, "vici rekey IKE_SA #%d", ike_id);
+ }
+ if (child_id)
+ {
+ DBG1(DBG_CFG, "vici rekey CHILD_SA #%d", child_id);
+ }
+ if (ike)
+ {
+ DBG1(DBG_CFG, "vici rekey IKE_SA '%s'", ike);
+ }
+ if (child)
+ {
+ DBG1(DBG_CFG, "vici rekey CHILD_SA '%s'", child);
+ }
+
+ isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
+ while (isas->enumerate(isas, &ike_sa))
+ {
+ if (child || child_id)
+ {
+ if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+ {
+ continue;
+ }
+ if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
+ {
+ continue;
+ }
+ csas = ike_sa->create_child_sa_enumerator(ike_sa);
+ while (csas->enumerate(csas, &child_sa))
+ {
+ if (child && !streq(child, child_sa->get_name(child_sa)))
+ {
+ continue;
+ }
+ if (child_id && child_sa->get_unique_id(child_sa) != child_id)
+ {
+ continue;
+ }
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_child_sa_job_create(
+ child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE),
+ ike_sa->get_my_host(ike_sa)));
+ found++;
+ }
+ csas->destroy(csas);
+ }
+ else if ((ike && streq(ike, ike_sa->get_name(ike_sa))) ||
+ (ike_id && ike_id == ike_sa->get_unique_id(ike_sa)))
+ {
+ lib->processor->queue_job(lib->processor,
+ (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE));
+ found++;
+ }
+ }
+ isas->destroy(isas);
+
+ builder = vici_builder_create();
+ if (!found)
+ {
+ errmsg = "no matching SAs to rekey found";
+ }
+ builder->add_kv(builder, "success", errmsg ? "no" : "yes");
+ builder->add_kv(builder, "matches", "%u", found);
+ if (errmsg)
+ {
+ builder->add_kv(builder, "errmsg", "%s", errmsg);
+ }
+ return builder->finalize(builder);
+}
+
/**
* Parse a peer-ip specified, which can be a subnet in CIDR notation, a range
* or a single IP address.
@@ -494,6 +590,7 @@ CALLBACK(redirect, vici_message_t*,
errmsg = "no matching SAs to redirect found";
}
builder->add_kv(builder, "success", errmsg ? "no" : "yes");
+ builder->add_kv(builder, "matches", "%u", found);
if (errmsg)
{
builder->add_kv(builder, "errmsg", "%s", errmsg);
@@ -565,7 +662,8 @@ CALLBACK(install, vici_message_t*,
{
case MODE_PASS:
case MODE_DROP:
- ok = charon->shunts->install(charon->shunts, child_cfg);
+ ok = charon->shunts->install(charon->shunts,
+ peer_cfg->get_name(peer_cfg), child_cfg);
break;
default:
ok = charon->traps->install(charon->traps, peer_cfg, child_cfg,
@@ -581,12 +679,15 @@ CALLBACK(install, vici_message_t*,
CALLBACK(uninstall, vici_message_t*,
private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
child_sa_t *child_sa;
enumerator_t *enumerator;
uint32_t reqid = 0;
- char *child;
+ char *child, *ike, *ns;
child = request->get_str(request, NULL, "child");
+ ike = request->get_str(request, NULL, "ike");
if (!child)
{
return send_reply(this, "missing configuration name");
@@ -594,15 +695,39 @@ CALLBACK(uninstall, vici_message_t*,
DBG1(DBG_CFG, "vici uninstall '%s'", child);
- if (charon->shunts->uninstall(charon->shunts, child))
+ if (!ike)
+ {
+ enumerator = charon->shunts->create_enumerator(charon->shunts);
+ while (enumerator->enumerate(enumerator, &ns, &child_cfg))
+ {
+ if (ns && streq(child, child_cfg->get_name(child_cfg)))
+ {
+ ike = strdup(ns);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (ike)
+ {
+ if (charon->shunts->uninstall(charon->shunts, ike, child))
+ {
+ free(ike);
+ return send_reply(this, NULL);
+ }
+ free(ike);
+ return send_reply(this, "uninstalling policy '%s' failed", child);
+ }
+ }
+ else if (charon->shunts->uninstall(charon->shunts, ike, child))
{
return send_reply(this, NULL);
}
enumerator = charon->traps->create_enumerator(charon->traps);
- while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ while (enumerator->enumerate(enumerator, &peer_cfg, &child_sa))
{
- if (streq(child, child_sa->get_name(child_sa)))
+ if ((!ike || streq(ike, peer_cfg->get_name(peer_cfg))) &&
+ streq(child, child_sa->get_name(child_sa)))
{
reqid = child_sa->get_reqid(child_sa);
break;
@@ -626,6 +751,7 @@ CALLBACK(reload_settings, vici_message_t*,
{
if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
{
+ charon->load_loggers(charon);
lib->plugins->reload(lib->plugins, NULL);
return send_reply(this, NULL);
}
@@ -646,6 +772,7 @@ static void manage_commands(private_vici_control_t *this, bool reg)
{
manage_command(this, "initiate", initiate, reg);
manage_command(this, "terminate", terminate, reg);
+ manage_command(this, "rekey", rekey, reg);
manage_command(this, "redirect", redirect, reg);
manage_command(this, "install", install, reg);
manage_command(this, "uninstall", uninstall, reg);
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
index baf285fb8..6c7c194c2 100644
--- a/src/libcharon/plugins/vici/vici_cred.c
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -1,9 +1,11 @@
/*
+ * Copyright (C) 2015-2016 Andreas Steffen
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
- * Copyright (C) 2015-2016 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -55,6 +57,11 @@ struct private_vici_cred_t {
mem_cred_t *creds;
/**
+ * separate credential set for token PINs
+ */
+ mem_cred_t *pins;
+
+ /**
* cache CRLs to disk?
*/
bool cachecrl;
@@ -249,6 +256,139 @@ CALLBACK(load_key, vici_message_t*,
return create_reply(NULL);
}
+CALLBACK(unload_key, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ chunk_t keyid;
+ char buf[BUF_LEN], *hex, *msg = NULL;
+
+ hex = message->get_str(message, NULL, "id");
+ if (!hex)
+ {
+ return create_reply("key id missing");
+ }
+ keyid = chunk_from_hex(chunk_from_str(hex), NULL);
+ snprintf(buf, sizeof(buf), "%+B", &keyid);
+ DBG1(DBG_CFG, "unloaded private key with id %s", buf);
+ if (this->creds->remove_key(this->creds, keyid))
+ { /* also remove any potential PIN associated with this id */
+ this->pins->remove_shared_unique(this->pins, buf);
+ }
+ else
+ {
+ msg = "key not found";
+ }
+ chunk_free(&keyid);
+ return create_reply(msg);
+}
+
+CALLBACK(get_keys, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ vici_builder_t *builder;
+ enumerator_t *enumerator;
+ private_key_t *private;
+ chunk_t keyid;
+
+ builder = vici_builder_create();
+ builder->begin_list(builder, "keys");
+
+ enumerator = this->creds->set.create_private_enumerator(&this->creds->set,
+ KEY_ANY, NULL);
+ while (enumerator->enumerate(enumerator, &private))
+ {
+ if (private->get_fingerprint(private, KEYID_PUBKEY_SHA1, &keyid))
+ {
+ builder->add_li(builder, "%+B", &keyid);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ builder->end_list(builder);
+ return builder->finalize(builder);
+}
+
+CALLBACK(load_token, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ vici_builder_t *builder;
+ private_key_t *key;
+ shared_key_t *shared = NULL;
+ identification_t *owner;
+ mem_cred_t *set = NULL;
+ chunk_t handle, fp;
+ char buf[BUF_LEN], *hex, *module, *pin, *unique = NULL;
+ int slot;
+
+ hex = message->get_str(message, NULL, "handle");
+ if (!hex)
+ {
+ return create_reply("keyid missing");
+ }
+ handle = chunk_from_hex(chunk_from_str(hex), NULL);
+ slot = message->get_int(message, -1, "slot");
+ module = message->get_str(message, NULL, "module");
+ pin = message->get_str(message, NULL, "pin");
+
+ if (pin)
+ { /* provide the pin in a temporary credential set to access the key */
+ shared = shared_key_create(SHARED_PIN, chunk_clone(chunk_from_str(pin)));
+ owner = identification_create_from_encoding(ID_KEY_ID, handle);
+ set = mem_cred_create();
+ set->add_shared(set, shared->get_ref(shared), owner, NULL);
+ lib->credmgr->add_local_set(lib->credmgr, &set->set, FALSE);
+ }
+ if (slot >= 0)
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
+ BUILD_PKCS11_KEYID, handle,
+ BUILD_PKCS11_SLOT, slot,
+ module ? BUILD_PKCS11_MODULE : BUILD_END, module,
+ BUILD_END);
+ }
+ else
+ {
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
+ BUILD_PKCS11_KEYID, handle,
+ module ? BUILD_PKCS11_MODULE : BUILD_END, module,
+ BUILD_END);
+ }
+ if (set)
+ {
+ lib->credmgr->remove_local_set(lib->credmgr, &set->set);
+ set->destroy(set);
+ }
+ if (!key)
+ {
+ chunk_free(&handle);
+ DESTROY_IF(shared);
+ return create_reply("loading private key from token failed");
+ }
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", "yes");
+ if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fp))
+ {
+ snprintf(buf, sizeof(buf), "%+B", &fp);
+ builder->add_kv(builder, "id", "%s", buf);
+ unique = buf;
+ }
+ if (shared && unique)
+ { /* use the handle as owner, but the key identifier as unique ID */
+ owner = identification_create_from_encoding(ID_KEY_ID, handle);
+ this->pins->add_shared_unique(this->pins, unique, shared,
+ linked_list_create_with_items(owner, NULL));
+ }
+ else
+ {
+ DESTROY_IF(shared);
+ }
+ DBG1(DBG_CFG, "loaded %N private key from token", key_type_names,
+ key->get_type(key));
+ this->creds->add_key(this->creds, key);
+ chunk_free(&handle);
+ return builder->finalize(builder);
+}
+
CALLBACK(shared_owners, bool,
linked_list_t *owners, vici_message_t *message, char *name, chunk_t value)
{
@@ -271,11 +411,12 @@ CALLBACK(load_shared, vici_message_t*,
shared_key_type_t type;
linked_list_t *owners;
chunk_t data;
- char *str, buf[512] = "";
+ char *unique, *str, buf[512] = "";
enumerator_t *enumerator;
identification_t *owner;
int len;
+ unique = message->get_str(message, NULL, "id");
str = message->get_str(message, NULL, "type");
if (!str)
{
@@ -289,6 +430,10 @@ CALLBACK(load_shared, vici_message_t*,
{
type = SHARED_EAP;
}
+ else if (strcaseeq(str, "ntlm"))
+ {
+ type = SHARED_NT_HASH;
+ }
else
{
return create_reply("invalid shared key type: %s", str);
@@ -322,15 +467,59 @@ CALLBACK(load_shared, vici_message_t*,
}
enumerator->destroy(enumerator);
- DBG1(DBG_CFG, "loaded %N shared key for: %s",
- shared_key_type_names, type, buf);
+ if (unique)
+ {
+ DBG1(DBG_CFG, "loaded %N shared key with id '%s' for: %s",
+ shared_key_type_names, type, unique, buf);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "loaded %N shared key for: %s",
+ shared_key_type_names, type, buf);
+ }
- this->creds->add_shared_list(this->creds,
+ this->creds->add_shared_unique(this->creds, unique,
shared_key_create(type, chunk_clone(data)), owners);
return create_reply(NULL);
}
+CALLBACK(unload_shared, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ char *unique;
+
+ unique = message->get_str(message, NULL, "id");
+ if (!unique)
+ {
+ return create_reply("unique identifier missing");
+ }
+ DBG1(DBG_CFG, "unloaded shared key with id '%s'", unique);
+ this->creds->remove_shared_unique(this->creds, unique);
+ return create_reply(NULL);
+}
+
+CALLBACK(get_shared, vici_message_t*,
+ private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+ vici_builder_t *builder;
+ enumerator_t *enumerator;
+ char *unique;
+
+ builder = vici_builder_create();
+ builder->begin_list(builder, "keys");
+
+ enumerator = this->creds->create_unique_shared_enumerator(this->creds);
+ while (enumerator->enumerate(enumerator, &unique))
+ {
+ builder->add_li(builder, "%s", unique);
+ }
+ enumerator->destroy(enumerator);
+
+ builder->end_list(builder);
+ return builder->finalize(builder);
+}
+
CALLBACK(clear_creds, vici_message_t*,
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
{
@@ -374,7 +563,12 @@ static void manage_commands(private_vici_cred_t *this, bool reg)
manage_command(this, "flush-certs", flush_certs, reg);
manage_command(this, "load-cert", load_cert, reg);
manage_command(this, "load-key", load_key, reg);
+ manage_command(this, "unload-key", unload_key, reg);
+ manage_command(this, "get-keys", get_keys, reg);
+ manage_command(this, "load-token", load_token, reg);
manage_command(this, "load-shared", load_shared, reg);
+ manage_command(this, "unload-shared", unload_shared, reg);
+ manage_command(this, "get-shared", get_shared, reg);
}
METHOD(vici_cred_t, add_cert, certificate_t*,
@@ -390,6 +584,8 @@ METHOD(vici_cred_t, destroy, void,
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
this->creds->destroy(this->creds);
+ lib->credmgr->remove_set(lib->credmgr, &this->pins->set);
+ this->pins->destroy(this->pins);
free(this);
}
@@ -414,6 +610,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
},
.dispatcher = dispatcher,
.creds = mem_cred_create(),
+ .pins = mem_cred_create(),
);
if (lib->settings->get_bool(lib->settings, "%s.cache_crls", FALSE, lib->ns))
@@ -422,6 +619,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
DBG1(DBG_CFG, "crl caching to %s enabled", CRL_DIR);
}
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+ lib->credmgr->add_set(lib->credmgr, &this->pins->set);
manage_commands(this, TRUE);
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c
index ffe0d61e5..596255b91 100644
--- a/src/libcharon/plugins/vici/vici_dispatcher.c
+++ b/src/libcharon/plugins/vici/vici_dispatcher.c
@@ -471,15 +471,17 @@ METHOD(vici_dispatcher_t, manage_event, void,
METHOD(vici_dispatcher_t, has_event_listeners, bool,
private_vici_dispatcher_t *this, char *name)
{
+ event_t *event;
bool retval = FALSE;
this->mutex->lock(this->mutex);
- if (this->events->get(this->events, name))
+ event = this->events->get(this->events, name);
+ if (event)
{
/* the entry might be getting destroyed, but returning
* false positive is not a problem as a later raise_event
* will check things again. */
- retval = TRUE;
+ retval = array_count(event->clients);
}
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/vici/vici_logger.c b/src/libcharon/plugins/vici/vici_logger.c
index 6d3584ebd..8e7bcfa1c 100644
--- a/src/libcharon/plugins/vici/vici_logger.c
+++ b/src/libcharon/plugins/vici/vici_logger.c
@@ -95,6 +95,11 @@ METHOD(logger_t, log_, void,
private_vici_logger_t *this, debug_t group, level_t level, int thread,
ike_sa_t* ike_sa, const char *msg)
{
+ if (!this->dispatcher->has_event_listeners(this->dispatcher, "log"))
+ {
+ return;
+ }
+
this->mutex->lock(this->mutex);
/* avoid recursive invocations by the vici subsystem */
@@ -130,6 +135,8 @@ METHOD(logger_t, log_, void,
METHOD(logger_t, get_level, level_t,
private_vici_logger_t *this, debug_t group)
{
+ /* anything higher might produce a loop as sending messages or listening
+ * for clients might cause log messages itself */
return LEVEL_CTRL;
}
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index 828b61927..c0f4e2de9 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -79,6 +79,42 @@ struct private_vici_query_t {
time_t uptime;
};
+static void add_mark(vici_builder_t *b, mark_t mark,
+ char *label, char *mask_label)
+{
+ if (mark.value | mark.mask)
+ {
+ b->add_kv(b, label, "%.8x", mark.value);
+ if (~mark.mask)
+ {
+ b->add_kv(b, mask_label, "%.8x", mark.mask);
+ }
+ }
+}
+
+/**
+ * List the mode of a CHILD_SA or config
+ */
+static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
+{
+ ipsec_mode_t mode;
+ char *sub_mode = "";
+
+ if (child || cfg)
+ {
+ if (!cfg)
+ {
+ cfg = child->get_config(child);
+ }
+ mode = child ? child->get_mode(child) : cfg->get_mode(cfg);
+ if (mode == MODE_TRANSPORT && cfg->use_proxy_mode(cfg))
+ { /* only report this if the negotiated mode is actually TRANSPORT */
+ sub_mode = "_PROXY";
+ }
+ b->add_kv(b, "mode", "%N%s", ipsec_mode_names, mode, sub_mode);
+ }
+}
+
/**
* List details of a CHILD_SA
*/
@@ -92,10 +128,11 @@ static void list_child(private_vici_query_t *this, vici_builder_t *b,
enumerator_t *enumerator;
traffic_selector_t *ts;
+ b->add_kv(b, "name", "%s", child->get_name(child));
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));
+ list_mode(b, child, NULL);
if (child->get_state(child) == CHILD_INSTALLED ||
child->get_state(child) == CHILD_REKEYING ||
child->get_state(child) == CHILD_REKEYED)
@@ -114,6 +151,8 @@ static void list_child(private_vici_query_t *this, vici_builder_t *b,
b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
}
+ add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
+ add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
proposal = child->get_proposal(child);
if (proposal)
{
@@ -382,6 +421,7 @@ CALLBACK(list_sas, vici_message_t*,
char *ike;
u_int ike_id;
bool bl;
+ char buf[BUF_LEN];
bl = request->get_str(request, NULL, "noblock") == NULL;
ike = request->get_str(request, NULL, "ike");
@@ -410,7 +450,9 @@ CALLBACK(list_sas, vici_message_t*,
csas = ike_sa->create_child_sa_enumerator(ike_sa);
while (csas->enumerate(csas, &child_sa))
{
- b->begin_section(b, child_sa->get_name(child_sa));
+ snprintf(buf, sizeof(buf), "%s-%u", child_sa->get_name(child_sa),
+ child_sa->get_unique_id(child_sa));
+ b->begin_section(b, buf);
list_child(this, b, child_sa, now);
b->end_section(b);
}
@@ -431,16 +473,21 @@ CALLBACK(list_sas, vici_message_t*,
/**
* Raise a list-policy event for given CHILD_SA
*/
-static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child)
+static void raise_policy(private_vici_query_t *this, u_int id, char *ike,
+ child_sa_t *child)
{
enumerator_t *enumerator;
traffic_selector_t *ts;
vici_builder_t *b;
+ char buf[BUF_LEN];
b = vici_builder_create();
- b->begin_section(b, child->get_name(child));
+ snprintf(buf, sizeof(buf), "%s/%s", ike, child->get_name(child));
+ b->begin_section(b, buf);
+ b->add_kv(b, "child", "%s", child->get_name(child));
+ b->add_kv(b, "ike", "%s", ike);
- b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
+ list_mode(b, child, NULL);
b->begin_list(b, "local-ts");
enumerator = child->create_ts_enumerator(child, TRUE);
@@ -469,18 +516,26 @@ static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child
/**
* Raise a list-policy event for given CHILD_SA config
*/
-static void raise_policy_cfg(private_vici_query_t *this, u_int id,
+static void raise_policy_cfg(private_vici_query_t *this, u_int id, char *ike,
child_cfg_t *cfg)
{
enumerator_t *enumerator;
linked_list_t *list;
traffic_selector_t *ts;
vici_builder_t *b;
+ char buf[BUF_LEN];
b = vici_builder_create();
- b->begin_section(b, cfg->get_name(cfg));
+ snprintf(buf, sizeof(buf), "%s%s%s", ike ? ike : "", ike ? "/" : "",
+ cfg->get_name(cfg));
+ b->begin_section(b, buf);
+ b->add_kv(b, "child", "%s", cfg->get_name(cfg));
+ if (ike)
+ {
+ b->add_kv(b, "ike", "%s", ike);
+ }
- b->add_kv(b, "mode", "%N", ipsec_mode_names, cfg->get_mode(cfg));
+ list_mode(b, NULL, cfg);
b->begin_list(b, "local-ts");
list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL);
@@ -516,25 +571,28 @@ CALLBACK(list_policies, vici_message_t*,
enumerator_t *enumerator;
vici_builder_t *b;
child_sa_t *child_sa;
+ peer_cfg_t *peer_cfg;
child_cfg_t *child_cfg;
bool drop, pass, trap;
- char *child;
+ char *child, *ike, *ns;
drop = request->get_str(request, NULL, "drop") != NULL;
pass = request->get_str(request, NULL, "pass") != NULL;
trap = request->get_str(request, NULL, "trap") != NULL;
child = request->get_str(request, NULL, "child");
+ ike = request->get_str(request, NULL, "ike");
if (trap)
{
enumerator = charon->traps->create_enumerator(charon->traps);
- while (enumerator->enumerate(enumerator, NULL, &child_sa))
+ while (enumerator->enumerate(enumerator, &peer_cfg, &child_sa))
{
- if (child && !streq(child, child_sa->get_name(child_sa)))
+ if ((ike && !streq(ike, peer_cfg->get_name(peer_cfg))) ||
+ (child && !streq(child, child_sa->get_name(child_sa))))
{
continue;
}
- raise_policy(this, id, child_sa);
+ raise_policy(this, id, peer_cfg->get_name(peer_cfg), child_sa);
}
enumerator->destroy(enumerator);
}
@@ -542,9 +600,10 @@ CALLBACK(list_policies, vici_message_t*,
if (drop || pass)
{
enumerator = charon->shunts->create_enumerator(charon->shunts);
- while (enumerator->enumerate(enumerator, &child_cfg))
+ while (enumerator->enumerate(enumerator, &ns, &child_cfg))
{
- if (child && !streq(child, child_cfg->get_name(child_cfg)))
+ if ((ike && !streq(ike, ns)) ||
+ (child && !streq(child, child_cfg->get_name(child_cfg))))
{
continue;
}
@@ -553,13 +612,13 @@ CALLBACK(list_policies, vici_message_t*,
case MODE_DROP:
if (drop)
{
- raise_policy_cfg(this, id, child_cfg);
+ raise_policy_cfg(this, id, ns, child_cfg);
}
break;
case MODE_PASS:
if (pass)
{
- raise_policy_cfg(this, id, child_cfg);
+ raise_policy_cfg(this, id, ns, child_cfg);
}
break;
default:
@@ -731,6 +790,8 @@ CALLBACK(list_conns, vici_message_t*,
peer_cfg->get_reauth_time(peer_cfg, FALSE));
b->add_kv(b, "rekey_time", "%u",
peer_cfg->get_rekey_time(peer_cfg, FALSE));
+ b->add_kv(b, "unique", "%N", unique_policy_names,
+ peer_cfg->get_unique_policy(peer_cfg));
build_auth_cfgs(peer_cfg, TRUE, b);
build_auth_cfgs(peer_cfg, FALSE, b);
@@ -742,8 +803,7 @@ CALLBACK(list_conns, vici_message_t*,
{
b->begin_section(b, child_cfg->get_name(child_cfg));
- b->add_kv(b, "mode", "%N", ipsec_mode_names,
- child_cfg->get_mode(child_cfg));
+ list_mode(b, NULL, child_cfg);
lft = child_cfg->get_lifetime(child_cfg, FALSE);
b->add_kv(b, "rekey_time", "%"PRIu64, lft->time.rekey);
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index 2e7bf0213..b85961387 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -367,7 +367,6 @@ 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@
@@ -402,6 +401,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index 541bec94c..a6554d6a9 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index 50a6c8065..87d627bc3 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index e2353a422..13fb71aef 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 048e4d580..821d46e6b 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -360,7 +360,6 @@ 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@
@@ -395,6 +394,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
diff --git a/src/libcharon/processing/jobs/delete_ike_sa_job.c b/src/libcharon/processing/jobs/delete_ike_sa_job.c
index a394e9df9..53a170510 100644
--- a/src/libcharon/processing/jobs/delete_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/delete_ike_sa_job.c
@@ -93,7 +93,8 @@ METHOD(job_t, execute, job_requeue_t,
}
else
{
- DBG1(DBG_JOB, "deleting half open IKE_SA after timeout");
+ DBG1(DBG_JOB, "deleting half open IKE_SA with %H after "
+ "timeout", ike_sa->get_other_host(ike_sa));
charon->bus->alert(charon->bus, ALERT_HALF_OPEN_TIMEOUT);
charon->ike_sa_manager->checkin_and_destroy(
charon->ike_sa_manager, ike_sa);
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
index 6c01ffe95..1082eae0b 100644
--- a/src/libcharon/processing/jobs/initiate_mediation_job.c
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -82,8 +82,25 @@ METHOD(job_t, initiate, job_requeue_t,
charon->ike_sa_manager->checkin(charon->ike_sa_manager, mediated_sa);
- mediation_cfg = mediated_cfg->get_mediated_by(mediated_cfg);
- mediation_cfg->get_ref(mediation_cfg);
+ mediation_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
+ mediated_cfg->get_mediated_by(mediated_cfg));
+ if (!mediation_cfg)
+ {
+ DBG1(DBG_IKE, "mediation connection '%s' not found, aborting",
+ mediated_cfg->get_mediated_by(mediated_cfg));
+ mediated_cfg->destroy(mediated_cfg);
+ return JOB_REQUEUE_NONE;
+ }
+ if (!mediation_cfg->is_mediation(mediation_cfg))
+ {
+ DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is no "
+ "mediation connection, aborting",
+ mediated_cfg->get_mediated_by(mediated_cfg),
+ mediated_cfg->get_name(mediated_cfg));
+ mediated_cfg->destroy(mediated_cfg);
+ mediation_cfg->destroy(mediation_cfg);
+ return JOB_REQUEUE_NONE;
+ }
enumerator = mediation_cfg->create_auth_cfg_enumerator(mediation_cfg,
TRUE);
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index 5e88ac230..654ec6abe 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -68,7 +68,9 @@ METHOD(job_t, execute, job_requeue_t,
mode = child_cfg->get_mode(child_cfg);
if (mode == MODE_PASS || mode == MODE_DROP)
{
- charon->shunts->install(charon->shunts, child_cfg);
+ charon->shunts->install(charon->shunts,
+ peer_cfg->get_name(peer_cfg),
+ child_cfg);
}
else
{
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index e4364de12..b9dd59b07 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -1,5 +1,5 @@
/*
- * Coypright (C) 2016 Andreas Steffen
+ * Copyright (C) 2016 Andreas Steffen
* Copyright (C) 2006-2016 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
@@ -479,7 +479,6 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
.dst = this->my_addr,
.spi = this->my_spi,
.proto = proto_ike2ip(this->protocol),
- .mark = this->mark_in,
};
kernel_ipsec_query_sa_t query = {};
@@ -495,9 +494,11 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
this->my_usetime = time;
}
- return SUCCESS;
}
- return FAILED;
+ else
+ {
+ status = FAILED;
+ }
}
}
}
@@ -526,9 +527,11 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
this->other_usetime = time;
}
- return SUCCESS;
}
- return FAILED;
+ else
+ {
+ status = FAILED;
+ }
}
}
}
@@ -797,7 +800,7 @@ METHOD(child_sa_t, install, status_t,
.dst = dst,
.spi = spi,
.proto = proto_ike2ip(this->protocol),
- .mark = inbound ? this->mark_in : this->mark_out,
+ .mark = inbound ? (mark_t){} : this->mark_out,
};
sa = (kernel_ipsec_add_sa_t){
.reqid = this->reqid,
@@ -1144,7 +1147,6 @@ METHOD(child_sa_t, update, status_t,
.dst = this->my_addr,
.spi = this->my_spi,
.proto = proto_ike2ip(this->protocol),
- .mark = this->mark_in,
};
kernel_ipsec_update_sa_t sa = {
.cpi = this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
@@ -1319,7 +1321,6 @@ METHOD(child_sa_t, destroy, void,
.dst = this->my_addr,
.spi = this->my_spi,
.proto = proto_ike2ip(this->protocol),
- .mark = this->mark_in,
};
kernel_ipsec_del_sa_t sa = {
.cpi = this->my_cpi,
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 7b87918d3..76e10691f 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -617,6 +617,12 @@ METHOD(ike_sa_t, set_message_id, void,
}
}
+METHOD(ike_sa_t, get_message_id, uint32_t,
+ private_ike_sa_t *this, bool initiate)
+{
+ return this->task_manager->get_mid(this->task_manager, initiate);
+}
+
METHOD(ike_sa_t, send_keepalive, void,
private_ike_sa_t *this, bool scheduled)
{
@@ -756,6 +762,10 @@ METHOD(ike_sa_t, send_dpd, status_t,
{
return INVALID_STATE;
}
+ if (this->version == IKEV1 && this->state == IKE_REKEYING)
+ { /* don't send DPDs for rekeyed IKEv1 SAs */
+ return SUCCESS;
+ }
delay = this->peer_cfg->get_dpd(this->peer_cfg);
if (this->task_manager->busy(this->task_manager))
{
@@ -2436,6 +2446,25 @@ static bool is_current_path_valid(private_ike_sa_t *this)
{
bool valid = FALSE;
host_t *src;
+
+ if (supports_extension(this, EXT_MOBIKE) &&
+ lib->settings->get_bool(lib->settings,
+ "%s.prefer_best_path", FALSE, lib->ns))
+ {
+ /* check if the current path is the best path; migrate otherwise */
+ src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
+ NULL);
+ if (src)
+ {
+ valid = src->ip_equals(src, this->my_host);
+ src->destroy(src);
+ }
+ if (!valid)
+ {
+ DBG1(DBG_IKE, "old path is not preferred anymore");
+ }
+ return valid;
+ }
src = charon->kernel->get_source_addr(charon->kernel, this->other_host,
this->my_host);
if (src)
@@ -2446,6 +2475,10 @@ static bool is_current_path_valid(private_ike_sa_t *this)
}
src->destroy(src);
}
+ if (!valid)
+ {
+ DBG1(DBG_IKE, "old path is not available anymore, try to find another");
+ }
return valid;
}
@@ -2472,7 +2505,6 @@ static bool is_any_path_valid(private_ike_sa_t *this)
break;
}
- DBG1(DBG_IKE, "old path is not available anymore, try to find another");
enumerator = create_peer_address_enumerator(this);
while (enumerator->enumerate(enumerator, &addr))
{
@@ -2511,6 +2543,16 @@ METHOD(ike_sa_t, roam, status_t,
break;
}
+ /* ignore roam events if MOBIKE is not supported/enabled and the local
+ * address is statically configured */
+ if (this->version == IKEV2 && !supports_extension(this, EXT_MOBIKE) &&
+ ike_cfg_has_address(this->ike_cfg, this->my_host, TRUE))
+ {
+ DBG2(DBG_IKE, "keeping statically configured path %H - %H",
+ this->my_host, this->other_host);
+ return SUCCESS;
+ }
+
/* keep existing path if possible */
if (is_current_path_valid(this))
{
@@ -2885,6 +2927,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.get_other_host = _get_other_host,
.set_other_host = _set_other_host,
.set_message_id = _set_message_id,
+ .get_message_id = _get_message_id,
.float_ports = _float_ports,
.update_hosts = _update_hosts,
.get_my_id = _get_my_id,
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 6f5040d7c..c8ba2fd2a 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -151,6 +151,11 @@ enum ike_extension_t {
* IKEv2 Redirect Mechanism, RFC 5685
*/
EXT_IKE_REDIRECTION = (1<<13),
+
+ /**
+ * IKEv2 Message ID sync, RFC 6311
+ */
+ EXT_IKE_MESSAGE_ID_SYNC = (1<<14),
};
/**
@@ -554,7 +559,7 @@ struct ike_sa_t {
void (*set_proposal)(ike_sa_t *this, proposal_t *proposal);
/**
- * Set the message id of the IKE_SA.
+ * Set the message ID of the IKE_SA.
*
* The IKE_SA stores two message IDs, one for initiating exchanges (send)
* and one to respond to exchanges (expect).
@@ -565,6 +570,17 @@ struct ike_sa_t {
void (*set_message_id)(ike_sa_t *this, bool initiate, uint32_t mid);
/**
+ * Get the message ID of the IKE_SA.
+ *
+ * The IKE_SA stores two message IDs, one for initiating exchanges (send)
+ * and one to respond to exchanges (expect).
+ *
+ * @param initiate TRUE to get message ID for initiating
+ * @return current message
+ */
+ uint32_t (*get_message_id)(ike_sa_t *this, bool initiate);
+
+ /**
* Add an additional address for the peer.
*
* In MOBIKE, a peer may transmit additional addresses where it is
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index ce44207c4..6bd49a086 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -2303,7 +2303,6 @@ ike_sa_manager_t *ike_sa_manager_create()
for (i = 0; i < this->segment_count; i++)
{
this->segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
- this->segments[i].count = 0;
}
/* we use the same table parameters for the table to track half-open SAs */
@@ -2312,7 +2311,6 @@ ike_sa_manager_t *ike_sa_manager_create()
for (i = 0; i < this->segment_count; i++)
{
this->half_open_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
- this->half_open_segments[i].count = 0;
}
/* also for the hash table used for duplicate tests */
@@ -2321,7 +2319,6 @@ ike_sa_manager_t *ike_sa_manager_create()
for (i = 0; i < this->segment_count; i++)
{
this->connected_peers_segments[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
- this->connected_peers_segments[i].count = 0;
}
/* and again for the table of hashes of seen initial IKE messages */
@@ -2330,7 +2327,6 @@ ike_sa_manager_t *ike_sa_manager_create()
for (i = 0; i < this->segment_count; i++)
{
this->init_hashes_segments[i].mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
- this->init_hashes_segments[i].count = 0;
}
this->reuse_ikesa = lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
index 5debeeb37..ddb8c650b 100644
--- a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
@@ -81,7 +81,7 @@ METHOD(authenticator_t, build, status_t,
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,
- this->id_payload, &hash))
+ this->id_payload, &hash, NULL))
{
free(dh.ptr);
return FAILED;
@@ -118,7 +118,7 @@ METHOD(authenticator_t, process, status_t,
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,
- this->id_payload, &hash))
+ this->id_payload, &hash, NULL))
{
free(dh.ptr);
return FAILED;
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
index eee7dd10b..344c1bf5d 100644
--- a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
@@ -102,7 +102,7 @@ METHOD(authenticator_t, build, status_t,
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,
- this->id_payload, &hash))
+ this->id_payload, &hash, &scheme))
{
private->destroy(private);
free(dh.ptr);
@@ -163,7 +163,7 @@ METHOD(authenticator_t, process, status_t,
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,
- this->id_payload, &hash))
+ this->id_payload, &hash, &scheme))
{
free(dh.ptr);
return FAILED;
diff --git a/src/libcharon/sa/ikev1/iv_manager.c b/src/libcharon/sa/ikev1/iv_manager.c
new file mode 100644
index 000000000..c9f737ccd
--- /dev/null
+++ b/src/libcharon/sa/ikev1/iv_manager.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2011-2016 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 "iv_manager.h"
+
+#include <collections/linked_list.h>
+
+/**
+ * Max. number of IVs/QMs to track.
+ */
+#define MAX_EXCHANGES_DEFAULT 3
+
+typedef struct private_iv_manager_t private_iv_manager_t;
+typedef struct iv_data_t iv_data_t;
+typedef struct qm_data_t qm_data_t;
+
+/**
+ * Data stored for IVs.
+ */
+struct iv_data_t {
+ /**
+ * message ID
+ */
+ uint32_t mid;
+
+ /**
+ * current IV
+ */
+ chunk_t iv;
+
+ /**
+ * last block of encrypted message
+ */
+ chunk_t last_block;
+};
+
+/**
+ * Private data of a iv_manager_t object.
+ */
+struct private_iv_manager_t {
+ /**
+ * Implement public interface.
+ */
+ iv_manager_t public;
+
+ /**
+ * Phase 1 IV.
+ */
+ iv_data_t phase1_iv;
+
+ /**
+ * Keep track of IVs for exchanges after phase 1. We store only a limited
+ * number of IVs in an MRU sort of way. Stores iv_data_t objects.
+ */
+ linked_list_t *ivs;
+
+ /**
+ * Keep track of Nonces during Quick Mode exchanges. Only a limited number
+ * of QMs are tracked at the same time. Stores qm_data_t objects.
+ */
+ linked_list_t *qms;
+
+ /**
+ * Max. number of IVs/Quick Modes to track.
+ */
+ int max_exchanges;
+
+ /**
+ * Hasher used for IV generation.
+ */
+ hasher_t *hasher;
+
+ /*
+ * Encryption algorithm the block size.
+ */
+ size_t block_size;
+};
+
+/**
+ * Data stored for Quick Mode exchanges.
+ */
+struct qm_data_t {
+ /**
+ * Message ID.
+ */
+ uint32_t mid;
+
+ /**
+ * Ni_b (Nonce from first message).
+ */
+ chunk_t n_i;
+
+ /**
+ * Nr_b (Nonce from second message).
+ */
+ chunk_t n_r;
+};
+
+/**
+ * Destroy an iv_data_t object.
+ */
+static void iv_data_destroy(iv_data_t *this)
+{
+ chunk_free(&this->last_block);
+ chunk_free(&this->iv);
+ free(this);
+}
+
+/**
+ * Destroy a qm_data_t object.
+ */
+static void qm_data_destroy(qm_data_t *this)
+{
+ chunk_free(&this->n_i);
+ chunk_free(&this->n_r);
+ free(this);
+}
+
+/**
+ * Generate an IV.
+ */
+static bool generate_iv(private_iv_manager_t *this, iv_data_t *iv)
+{
+ if (iv->mid == 0 || iv->iv.ptr)
+ { /* use last block of previous encrypted message */
+ chunk_free(&iv->iv);
+ iv->iv = iv->last_block;
+ iv->last_block = chunk_empty;
+ }
+ else
+ {
+ /* initial phase 2 IV = hash(last_phase1_block | mid) */
+ uint32_t net;;
+ chunk_t data;
+
+ net = htonl(iv->mid);
+ data = chunk_cata("cc", this->phase1_iv.iv, chunk_from_thing(net));
+ if (!this->hasher->allocate_hash(this->hasher, data, &iv->iv))
+ {
+ return FALSE;
+ }
+ if (iv->iv.len > this->block_size)
+ {
+ iv->iv.len = this->block_size;
+ }
+ }
+ DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv);
+ return TRUE;
+}
+
+/**
+ * Try to find an IV for the given message ID, if not found, generate it.
+ */
+static iv_data_t *lookup_iv(private_iv_manager_t *this, uint32_t mid)
+{
+ enumerator_t *enumerator;
+ iv_data_t *iv, *found = NULL;
+
+ if (mid == 0)
+ {
+ return &this->phase1_iv;
+ }
+
+ enumerator = this->ivs->create_enumerator(this->ivs);
+ while (enumerator->enumerate(enumerator, &iv))
+ {
+ if (iv->mid == mid)
+ { /* IV gets moved to the front of the list */
+ this->ivs->remove_at(this->ivs, enumerator);
+ found = iv;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ INIT(found,
+ .mid = mid,
+ );
+ if (!generate_iv(this, found))
+ {
+ iv_data_destroy(found);
+ return NULL;
+ }
+ }
+ this->ivs->insert_first(this->ivs, found);
+ /* remove least recently used IV if maximum reached */
+ if (this->ivs->get_count(this->ivs) > this->max_exchanges &&
+ this->ivs->remove_last(this->ivs, (void**)&iv) == SUCCESS)
+ {
+ iv_data_destroy(iv);
+ }
+ return found;
+}
+
+METHOD(iv_manager_t, init_iv_chain, bool,
+ private_iv_manager_t *this, chunk_t data, hasher_t *hasher,
+ size_t block_size)
+{
+ this->hasher = hasher;
+ this->block_size = block_size;
+
+ if (!this->hasher->allocate_hash(this->hasher, data, &this->phase1_iv.iv))
+ {
+ return FALSE;
+ }
+ if (this->phase1_iv.iv.len > this->block_size)
+ {
+ this->phase1_iv.iv.len = this->block_size;
+ }
+ DBG4(DBG_IKE, "initial IV %B", &this->phase1_iv.iv);
+ return TRUE;
+}
+
+METHOD(iv_manager_t, get_iv, bool,
+ private_iv_manager_t *this, uint32_t mid, chunk_t *out)
+{
+ iv_data_t *iv;
+
+ iv = lookup_iv(this, mid);
+ if (iv)
+ {
+ *out = iv->iv;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(iv_manager_t, update_iv, bool,
+ private_iv_manager_t *this, uint32_t mid, chunk_t last_block)
+{
+ iv_data_t *iv = lookup_iv(this, mid);
+ if (iv)
+ { /* update last block */
+ chunk_free(&iv->last_block);
+ iv->last_block = chunk_clone(last_block);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(iv_manager_t, confirm_iv, bool,
+ private_iv_manager_t *this, uint32_t mid)
+{
+ iv_data_t *iv = lookup_iv(this, mid);
+ if (iv)
+ {
+ return generate_iv(this, iv);
+ }
+ return FALSE;
+}
+
+METHOD(iv_manager_t, lookup_quick_mode, void,
+ private_iv_manager_t *this, uint32_t mid, chunk_t **n_i, chunk_t **n_r)
+{
+ enumerator_t *enumerator;
+ qm_data_t *qm, *found = NULL;
+
+ enumerator = this->qms->create_enumerator(this->qms);
+ while (enumerator->enumerate(enumerator, &qm))
+ {
+ if (qm->mid == mid)
+ { /* state gets moved to the front of the list */
+ this->qms->remove_at(this->qms, enumerator);
+ found = qm;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ INIT(found,
+ .mid = mid,
+ );
+ }
+
+ *n_i = &found->n_i;
+ *n_r = &found->n_r;
+
+ this->qms->insert_first(this->qms, found);
+ /* remove least recently used state if maximum reached */
+ if (this->qms->get_count(this->qms) > this->max_exchanges &&
+ this->qms->remove_last(this->qms, (void**)&qm) == SUCCESS)
+ {
+ qm_data_destroy(qm);
+ }
+}
+
+METHOD(iv_manager_t, remove_quick_mode, void,
+ private_iv_manager_t *this, uint32_t mid)
+{
+ enumerator_t *enumerator;
+ qm_data_t *qm;
+
+ enumerator = this->qms->create_enumerator(this->qms);
+ while (enumerator->enumerate(enumerator, &qm))
+ {
+ if (qm->mid == mid)
+ {
+ this->qms->remove_at(this->qms, enumerator);
+ qm_data_destroy(qm);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(iv_manager_t, destroy, void,
+ private_iv_manager_t *this)
+{
+ chunk_free(&this->phase1_iv.iv);
+ chunk_free(&this->phase1_iv.last_block);
+ this->ivs->destroy_function(this->ivs, (void*)iv_data_destroy);
+ this->qms->destroy_function(this->qms, (void*)qm_data_destroy);
+ free(this);
+}
+
+iv_manager_t *iv_manager_create(int max_exchanges)
+{
+ private_iv_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .init_iv_chain = _init_iv_chain,
+ .get_iv = _get_iv,
+ .update_iv = _update_iv,
+ .confirm_iv = _confirm_iv,
+ .lookup_quick_mode = _lookup_quick_mode,
+ .remove_quick_mode = _remove_quick_mode,
+ .destroy = _destroy,
+ },
+ .ivs = linked_list_create(),
+ .qms = linked_list_create(),
+ .max_exchanges = max_exchanges,
+ );
+
+ if (!this->max_exchanges)
+ {
+ this->max_exchanges = lib->settings->get_int(lib->settings,
+ "%s.max_ikev1_exchanges", MAX_EXCHANGES_DEFAULT, lib->ns);
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev1/iv_manager.h b/src/libcharon/sa/ikev1/iv_manager.h
new file mode 100644
index 000000000..c5273fed9
--- /dev/null
+++ b/src/libcharon/sa/ikev1/iv_manager.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011-2016 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 iv_manager iv_manager
+ * @{ @ingroup ikev1
+ */
+
+#ifndef IV_MANAGER_H_
+#define IV_MANAGER_H_
+
+#include <utils/chunk.h>
+#include <crypto/hashers/hasher.h>
+
+typedef struct iv_manager_t iv_manager_t;
+
+/**
+ * IV and QM managing instance for IKEv1. Keeps track of phase 2 exchanges
+ * and IV, as well as the phase 1 IV.
+ */
+struct iv_manager_t {
+
+ /**
+ * Set the value of the first phase1 IV.
+ *
+ * @param data input to calc initial IV from (g^xi | g^xr)
+ * @param hasher hasher to be used for IV calculation
+ * (shared with keymat, must not be destroyed here)
+ * @param block_size cipher block size of aead
+ * @return TRUE for success, FALSE otherwise
+ */
+ bool (*init_iv_chain)(iv_manager_t *this, chunk_t data, hasher_t *hasher,
+ size_t block_size);
+
+ /**
+ * Returns the IV for a message with the given message ID.
+ *
+ * The return chunk contains internal data and is valid until the next
+ * get_iv/udpate_iv/confirm_iv() call.
+ *
+ * @param mid message ID
+ * @param iv chunk receiving IV, internal data
+ * @return TRUE if IV allocated successfully
+ */
+ bool (*get_iv)(iv_manager_t *this, uint32_t mid, chunk_t *iv);
+
+ /**
+ * Updates the IV for the next message with the given message ID.
+ *
+ * A call of confirm_iv() is required in order to actually make the IV
+ * available. This is needed for the inbound case where we store the last
+ * block of the encrypted message but want to update the IV only after
+ * verification of the decrypted message.
+ *
+ * @param mid message ID
+ * @param last_block last block of encrypted message (gets cloned)
+ * @return TRUE if IV updated successfully
+ */
+ bool (*update_iv)(iv_manager_t *this, uint32_t mid, chunk_t last_block);
+
+ /**
+ * Confirms the updated IV for the given message ID.
+ *
+ * To actually make the new IV available via get_iv() this method has to
+ * be called after update_iv().
+ *
+ * @param mid message ID
+ * @return TRUE if IV confirmed successfully
+ */
+ bool (*confirm_iv)(iv_manager_t *this, uint32_t mid);
+
+ /**
+ * Try to find a QM for the given message ID, if not found, generate it.
+ * The nonces shall be assigned by the caller if they are not set yet.
+ *
+ * @param mid message ID
+ * @param n_i chunk pointer to contain Ni_b (Nonce from first
+ * message)
+ * @param n_r chunk pointer to contain Nr_b (Nonce from second
+ * message)
+ */
+ void (*lookup_quick_mode)(iv_manager_t *this, uint32_t mid, chunk_t **n_i,
+ chunk_t **n_r);
+
+ /**
+ * Remove the QM for the given message ID.
+ *
+ * @param mid message ID
+ */
+ void (*remove_quick_mode)(iv_manager_t *this, uint32_t mid);
+
+ /*
+ * Destroy a iv_manager_t.
+ */
+ void (*destroy)(iv_manager_t *this);
+};
+
+/**
+ * Create an IV and QM manager which is able to store up to max_exchanges
+ * initialization vectors and quick modes.
+ *
+ * @param max_exchanges maximum number of IVs and QMs to be stored, set
+ * to 0 to use default (3, or as configured)
+ * @return IV and QM manager instance
+ */
+iv_manager_t *iv_manager_create(int max_exchanges);
+
+#endif /** IV_MANAGER_H_ @}*/
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c
index d1d4cbd9b..673a7a131 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.c
+++ b/src/libcharon/sa/ikev1/keymat_v1.c
@@ -16,30 +16,13 @@
#include "keymat_v1.h"
#include <daemon.h>
+#include <sa/ikev1/iv_manager.h>
#include <encoding/generator.h>
#include <encoding/payloads/nonce_payload.h>
-#include <collections/linked_list.h>
typedef struct private_keymat_v1_t private_keymat_v1_t;
/**
- * Max. number of IVs/QMs to track.
- */
-#define MAX_EXCHANGES_DEFAULT 3
-
-/**
- * Data stored for IVs
- */
-typedef struct {
- /** message ID */
- uint32_t mid;
- /** current IV */
- chunk_t iv;
- /** last block of encrypted message */
- chunk_t last_block;
-} iv_data_t;
-
-/**
* Private data of an keymat_t object.
*/
struct private_keymat_v1_t {
@@ -85,61 +68,11 @@ struct private_keymat_v1_t {
chunk_t skeyid_a;
/**
- * Phase 1 IV
- */
- iv_data_t phase1_iv;
-
- /**
- * Keep track of IVs for exchanges after phase 1. We store only a limited
- * number of IVs in an MRU sort of way. Stores iv_data_t objects.
- */
- linked_list_t *ivs;
-
- /**
- * Keep track of Nonces during Quick Mode exchanges. Only a limited number
- * of QMs are tracked at the same time. Stores qm_data_t objects.
+ * IV and QM manager
*/
- linked_list_t *qms;
-
- /**
- * Max. number of IVs/Quick Modes to track.
- */
- int max_exchanges;
+ iv_manager_t *iv_manager;
};
-
-/**
- * Destroy an iv_data_t object.
- */
-static void iv_data_destroy(iv_data_t *this)
-{
- chunk_free(&this->last_block);
- chunk_free(&this->iv);
- free(this);
-}
-
-/**
- * Data stored for Quick Mode exchanges
- */
-typedef struct {
- /** message ID */
- uint32_t mid;
- /** Ni_b (Nonce from first message) */
- chunk_t n_i;
- /** Nr_b (Nonce from second message) */
- chunk_t n_r;
-} qm_data_t;
-
-/**
- * Destroy a qm_data_t object.
- */
-static void qm_data_destroy(qm_data_t *this)
-{
- chunk_free(&this->n_i);
- chunk_free(&this->n_r);
- free(this);
-}
-
/**
* Constants used in key derivation.
*/
@@ -567,17 +500,8 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
/* initial IV = hash(g^xi | g^xr) */
data = chunk_cata("cc", g_xi, g_xr);
chunk_free(&dh_me);
- if (!this->hasher->allocate_hash(this->hasher, data, &this->phase1_iv.iv))
- {
- return FALSE;
- }
- if (this->phase1_iv.iv.len > this->aead->get_block_size(this->aead))
- {
- this->phase1_iv.iv.len = this->aead->get_block_size(this->aead);
- }
- DBG4(DBG_IKE, "initial IV %B", &this->phase1_iv.iv);
-
- return TRUE;
+ return this->iv_manager->init_iv_chain(this->iv_manager, data, this->hasher,
+ this->aead->get_block_size(this->aead));
}
METHOD(keymat_v1_t, derive_child_keys, bool,
@@ -748,7 +672,8 @@ METHOD(keymat_v1_t, get_hasher, hasher_t*,
METHOD(keymat_v1_t, get_hash, bool,
private_keymat_v1_t *this, bool initiator, chunk_t dh, chunk_t dh_other,
- ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash)
+ ike_sa_id_t *ike_sa_id, chunk_t sa_i, chunk_t id, chunk_t *hash,
+ signature_scheme_t *scheme)
{
chunk_t data;
uint64_t spi, spi_other;
@@ -843,47 +768,11 @@ static chunk_t get_message_data(message_t *message, generator_t *generator)
return generator->get_chunk(generator, &lenpos);
}
-/**
- * Try to find data about a Quick Mode with the given message ID,
- * if none is found, state is generated.
- */
-static qm_data_t *lookup_quick_mode(private_keymat_v1_t *this, uint32_t mid)
-{
- enumerator_t *enumerator;
- qm_data_t *qm, *found = NULL;
-
- enumerator = this->qms->create_enumerator(this->qms);
- while (enumerator->enumerate(enumerator, &qm))
- {
- if (qm->mid == mid)
- { /* state gets moved to the front of the list */
- this->qms->remove_at(this->qms, enumerator);
- found = qm;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (!found)
- {
- INIT(found,
- .mid = mid,
- );
- }
- this->qms->insert_first(this->qms, found);
- /* remove least recently used state if maximum reached */
- if (this->qms->get_count(this->qms) > this->max_exchanges &&
- this->qms->remove_last(this->qms, (void**)&qm) == SUCCESS)
- {
- qm_data_destroy(qm);
- }
- return found;
-}
-
METHOD(keymat_v1_t, get_hash_phase2, bool,
private_keymat_v1_t *this, message_t *message, chunk_t *hash)
{
uint32_t mid, mid_n;
- chunk_t data = chunk_empty;
+ chunk_t data = chunk_empty, *n_i, *n_r;
bool add_message = TRUE;
char *name = "Hash";
@@ -907,34 +796,34 @@ METHOD(keymat_v1_t, get_hash_phase2, bool,
{
case QUICK_MODE:
{
- qm_data_t *qm = lookup_quick_mode(this, mid);
- if (!qm->n_i.ptr)
+ this->iv_manager->lookup_quick_mode(this->iv_manager, mid, &n_i,
+ &n_r);
+ if (!n_i->ptr)
{ /* Hash(1) = prf(SKEYID_a, M-ID | Message after HASH payload) */
name = "Hash(1)";
- if (!get_nonce(message, &qm->n_i))
+ if (!get_nonce(message, n_i))
{
return FALSE;
}
data = chunk_from_thing(mid_n);
}
- else if (!qm->n_r.ptr)
+ else if (!n_r->ptr)
{ /* Hash(2) = prf(SKEYID_a, M-ID | Ni_b | Message after HASH) */
name = "Hash(2)";
- if (!get_nonce(message, &qm->n_r))
+ if (!get_nonce(message, n_r))
{
return FALSE;
}
- data = chunk_cata("cc", chunk_from_thing(mid_n), qm->n_i);
+ data = chunk_cata("cc", chunk_from_thing(mid_n), *n_i);
}
else
{ /* Hash(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
name = "Hash(3)";
data = chunk_cata("cccc", octet_0, chunk_from_thing(mid_n),
- qm->n_i, qm->n_r);
+ *n_i, *n_r);
add_message = FALSE;
/* we don't need the state anymore */
- this->qms->remove(this->qms, qm, NULL);
- qm_data_destroy(qm);
+ this->iv_manager->remove_quick_mode(this->iv_manager, mid);
}
break;
}
@@ -976,119 +865,22 @@ METHOD(keymat_v1_t, get_hash_phase2, bool,
return TRUE;
}
-/**
- * Generate an IV
- */
-static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv)
-{
- if (iv->mid == 0 || iv->iv.ptr)
- { /* use last block of previous encrypted message */
- chunk_free(&iv->iv);
- iv->iv = iv->last_block;
- iv->last_block = chunk_empty;
- }
- else
- {
- /* initial phase 2 IV = hash(last_phase1_block | mid) */
- uint32_t net;;
- chunk_t data;
-
- net = htonl(iv->mid);
- data = chunk_cata("cc", this->phase1_iv.iv, chunk_from_thing(net));
- if (!this->hasher->allocate_hash(this->hasher, data, &iv->iv))
- {
- return FALSE;
- }
- if (iv->iv.len > this->aead->get_block_size(this->aead))
- {
- iv->iv.len = this->aead->get_block_size(this->aead);
- }
- }
- DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv);
- return TRUE;
-}
-
-/**
- * Try to find an IV for the given message ID, if not found, generate it.
- */
-static iv_data_t *lookup_iv(private_keymat_v1_t *this, uint32_t mid)
-{
- enumerator_t *enumerator;
- iv_data_t *iv, *found = NULL;
-
- if (mid == 0)
- {
- return &this->phase1_iv;
- }
-
- enumerator = this->ivs->create_enumerator(this->ivs);
- while (enumerator->enumerate(enumerator, &iv))
- {
- if (iv->mid == mid)
- { /* IV gets moved to the front of the list */
- this->ivs->remove_at(this->ivs, enumerator);
- found = iv;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (!found)
- {
- INIT(found,
- .mid = mid,
- );
- if (!generate_iv(this, found))
- {
- iv_data_destroy(found);
- return NULL;
- }
- }
- this->ivs->insert_first(this->ivs, found);
- /* remove least recently used IV if maximum reached */
- if (this->ivs->get_count(this->ivs) > this->max_exchanges &&
- this->ivs->remove_last(this->ivs, (void**)&iv) == SUCCESS)
- {
- iv_data_destroy(iv);
- }
- return found;
-}
-
METHOD(keymat_v1_t, get_iv, bool,
private_keymat_v1_t *this, uint32_t mid, chunk_t *out)
{
- iv_data_t *iv;
-
- iv = lookup_iv(this, mid);
- if (iv)
- {
- *out = iv->iv;
- return TRUE;
- }
- return FALSE;
+ return this->iv_manager->get_iv(this->iv_manager, mid, out);
}
METHOD(keymat_v1_t, update_iv, bool,
private_keymat_v1_t *this, uint32_t mid, chunk_t last_block)
{
- iv_data_t *iv = lookup_iv(this, mid);
- if (iv)
- { /* update last block */
- chunk_free(&iv->last_block);
- iv->last_block = chunk_clone(last_block);
- return TRUE;
- }
- return FALSE;
+ return this->iv_manager->update_iv(this->iv_manager, mid, last_block);
}
METHOD(keymat_v1_t, confirm_iv, bool,
private_keymat_v1_t *this, uint32_t mid)
{
- iv_data_t *iv = lookup_iv(this, mid);
- if (iv)
- {
- return generate_iv(this, iv);
- }
- return FALSE;
+ return this->iv_manager->confirm_iv(this->iv_manager, mid);
}
METHOD(keymat_t, get_version, ike_version_t,
@@ -1124,10 +916,7 @@ METHOD(keymat_t, destroy, void,
DESTROY_IF(this->hasher);
chunk_clear(&this->skeyid_d);
chunk_clear(&this->skeyid_a);
- chunk_free(&this->phase1_iv.iv);
- chunk_free(&this->phase1_iv.last_block);
- this->ivs->destroy_function(this->ivs, (void*)iv_data_destroy);
- this->qms->destroy_function(this->qms, (void*)qm_data_destroy);
+ this->iv_manager->destroy(this->iv_manager);
free(this);
}
@@ -1157,12 +946,8 @@ keymat_v1_t *keymat_v1_create(bool initiator)
.update_iv = _update_iv,
.confirm_iv = _confirm_iv,
},
- .ivs = linked_list_create(),
- .qms = linked_list_create(),
.initiator = initiator,
- .max_exchanges = lib->settings->get_int(lib->settings,
- "%s.max_ikev1_exchanges", MAX_EXCHANGES_DEFAULT, lib->ns),
+ .iv_manager = iv_manager_create(0),
);
-
return &this->public;
}
diff --git a/src/libcharon/sa/ikev1/keymat_v1.h b/src/libcharon/sa/ikev1/keymat_v1.h
index 46eeea8b6..ada5bdb04 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.h
+++ b/src/libcharon/sa/ikev1/keymat_v1.h
@@ -102,11 +102,14 @@ struct keymat_v1_t {
* @param sa_i encoded SA payload of initiator
* @param id encoded IDii payload for HASH_I (IDir for HASH_R)
* @param hash chunk receiving allocated HASH data
+ * @param scheme pointer to signature scheme in case it needs to be
+ * modified by the keymat implementation
* @return TRUE if hash allocated successfully
*/
bool (*get_hash)(keymat_v1_t *this, bool initiator,
chunk_t dh, chunk_t dh_other, ike_sa_id_t *ike_sa_id,
- chunk_t sa_i, chunk_t id, chunk_t *hash);
+ chunk_t sa_i, chunk_t id, chunk_t *hash,
+ signature_scheme_t *scheme);
/**
* Get HASH data for integrity/authentication in Phase 2 exchanges.
@@ -118,39 +121,17 @@ struct keymat_v1_t {
bool (*get_hash_phase2)(keymat_v1_t *this, message_t *message, chunk_t *hash);
/**
- * Returns the IV for a message with the given message ID.
- *
- * The return chunk contains internal data and is valid until the next
- * get_iv/udpate_iv/confirm_iv call.
- *
- * @param mid message ID
- * @param iv chunk receiving IV, internal data
- * @return TRUE if IV allocated successfully
+ * @see iv_manager_t.get_iv
*/
bool (*get_iv)(keymat_v1_t *this, uint32_t mid, chunk_t *iv);
/**
- * Updates the IV for the next message with the given message ID.
- *
- * A call of confirm_iv() is required in order to actually make the IV
- * available. This is needed for the inbound case where we store the last
- * block of the encrypted message but want to update the IV only after
- * verification of the decrypted message.
- *
- * @param mid message ID
- * @param last_block last block of encrypted message (gets cloned)
- * @return TRUE if IV updated successfully
+ * @see iv_manager_t.update_iv
*/
bool (*update_iv)(keymat_v1_t *this, uint32_t mid, chunk_t last_block);
/**
- * Confirms the updated IV for the given message ID.
- *
- * To actually make the new IV available via get_iv this method has to
- * be called after update_iv.
- *
- * @param mid message ID
- * @return TRUE if IV confirmed successfully
+ * @see iv_manager_t.confirm_iv
*/
bool (*confirm_iv)(keymat_v1_t *this, uint32_t mid);
};
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index c968b2a9c..adce59f7e 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -113,22 +113,8 @@ static shared_key_t *lookup_shared_key(private_phase1_t *this,
auth_cfg_t *my_auth, *other_auth;
enumerator_t *enumerator;
- /* try to get a PSK for IP addresses */
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
- my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
- other_id = identification_create_from_sockaddr(other->get_sockaddr(other));
- if (my_id && other_id)
- {
- shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
- my_id, other_id);
- }
- DESTROY_IF(my_id);
- DESTROY_IF(other_id);
- if (shared_key)
- {
- return shared_key;
- }
if (peer_cfg)
{ /* as initiator or aggressive responder, use identities */
@@ -156,39 +142,51 @@ static shared_key_t *lookup_shared_key(private_phase1_t *this,
}
}
}
- return shared_key;
}
- /* as responder, we try to find a config by IP */
- enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
- me, other, NULL, NULL, IKEV1);
- while (enumerator->enumerate(enumerator, &peer_cfg))
- {
- my_auth = get_auth_cfg(peer_cfg, TRUE);
- other_auth = get_auth_cfg(peer_cfg, FALSE);
- if (my_auth && other_auth)
+ else
+ { /* as responder, we try to find a config by IP addresses and use the
+ * configured identities to find the PSK */
+ enumerator = charon->backends->create_peer_cfg_enumerator(
+ charon->backends, me, other, NULL, NULL, IKEV1);
+ while (enumerator->enumerate(enumerator, &peer_cfg))
{
- my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
- other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
- if (my_id)
+ my_auth = get_auth_cfg(peer_cfg, TRUE);
+ other_auth = get_auth_cfg(peer_cfg, FALSE);
+ if (my_auth && other_auth)
{
- shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
- my_id, other_id);
- if (shared_key)
- {
- break;
- }
- else
+ my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
+ other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
+ if (my_id)
{
+ shared_key = lib->credmgr->get_shared(lib->credmgr,
+ SHARED_IKE, my_id, other_id);
+ if (shared_key)
+ {
+ break;
+ }
DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
my_id, me, other_id, other);
}
}
}
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
if (!shared_key)
- {
- DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
+ { /* try to get a PSK for IP addresses */
+ my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
+ other_id = identification_create_from_sockaddr(
+ other->get_sockaddr(other));
+ if (my_id && other_id)
+ {
+ shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
+ my_id, other_id);
+ }
+ DESTROY_IF(my_id);
+ DESTROY_IF(other_id);
+ if (!shared_key)
+ {
+ DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
+ }
}
return shared_key;
}
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 3b0c1cfd1..1da17ee50 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -367,7 +367,7 @@ static status_t retransmit_packet(private_task_manager_t *this, uint32_t seqnr,
send_packets(this, packets);
lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
retransmit_job_create(seqnr, this->ike_sa->get_id(this->ike_sa)), t);
- return NEED_MORE;
+ return SUCCESS;
}
METHOD(task_manager_t, retransmit, status_t,
@@ -380,10 +380,9 @@ METHOD(task_manager_t, retransmit, status_t,
{
status = retransmit_packet(this, seqnr, this->initiating.mid,
this->initiating.retransmitted, this->initiating.packets);
- if (status == NEED_MORE)
+ if (status == SUCCESS)
{
this->initiating.retransmitted++;
- status = SUCCESS;
}
}
if (seqnr == this->responding.seqnr &&
@@ -391,10 +390,9 @@ METHOD(task_manager_t, retransmit, status_t,
{
status = retransmit_packet(this, seqnr, this->responding.mid,
this->responding.retransmitted, this->responding.packets);
- if (status == NEED_MORE)
+ if (status == SUCCESS)
{
this->responding.retransmitted++;
- status = SUCCESS;
}
}
return status;
@@ -554,6 +552,12 @@ METHOD(task_manager_t, initiate, status_t,
new_mid = TRUE;
break;
}
+ if (activate_task(this, TASK_ISAKMP_DPD))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
break;
default:
break;
@@ -685,13 +689,9 @@ METHOD(task_manager_t, initiate, status_t,
message->destroy(message);
return retransmit(this, this->initiating.seqnr);
}
- if (keep)
- { /* keep the packet for retransmission, the responder might request it */
- send_packets(this, this->initiating.packets);
- }
- else
+ send_packets(this, this->initiating.packets);
+ if (!keep)
{
- send_packets(this, this->initiating.packets);
clear_packets(this->initiating.packets);
}
message->destroy(message);
@@ -1902,6 +1902,12 @@ METHOD(task_manager_t, incr_mid, void,
{
}
+METHOD(task_manager_t, get_mid, uint32_t,
+ private_task_manager_t *this, bool initiate)
+{
+ return initiate ? this->initiating.mid : this->responding.mid;
+}
+
METHOD(task_manager_t, reset, void,
private_task_manager_t *this, uint32_t initiate, uint32_t respond)
{
@@ -2005,6 +2011,7 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.initiate = _initiate,
.retransmit = _retransmit,
.incr_mid = _incr_mid,
+ .get_mid = _get_mid,
.reset = _reset,
.adopt_tasks = _adopt_tasks,
.adopt_child_tasks = _adopt_child_tasks,
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 6b896416a..bbb885850 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -703,25 +703,30 @@ static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
{
identification_t *id;
id_payload_t *nat_oa;
- host_t *src, *dst;
+ host_t *init, *resp;
payload_type_t nat_oa_payload_type;
- src = message->get_source(message);
- dst = message->get_destination(message);
-
- src = this->initiator ? src : dst;
- dst = this->initiator ? dst : src;
+ if (this->initiator)
+ {
+ init = message->get_source(message);
+ resp = message->get_destination(message);
+ }
+ else
+ {
+ init = message->get_destination(message);
+ resp = message->get_source(message);
+ }
nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
/* first NAT-OA is the initiator's address */
- id = identification_create_from_sockaddr(src->get_sockaddr(src));
+ id = identification_create_from_sockaddr(init->get_sockaddr(init));
nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
message->add_payload(message, (payload_t*)nat_oa);
id->destroy(id);
/* second NAT-OA is that of the responder */
- id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
+ id = identification_create_from_sockaddr(resp->get_sockaddr(resp));
nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
message->add_payload(message, (payload_t*)nat_oa);
id->destroy(id);
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 592f49770..19ea72d0b 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -217,7 +217,8 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
}
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
- this->nonce, id, this->reserved, &octets))
+ this->nonce, id, this->reserved, &octets,
+ schemes))
{
enumerator = array_create_enumerator(schemes);
while (enumerator->enumerate(enumerator, &schemep))
@@ -247,6 +248,32 @@ static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
}
/**
+ * Get the auth octets and the signature scheme (in case it is changed by the
+ * keymat).
+ */
+static bool get_auth_octets_scheme(private_pubkey_authenticator_t *this,
+ bool verify, identification_t *id,
+ chunk_t *octets, signature_scheme_t *scheme)
+{
+ keymat_v2_t *keymat;
+ array_t *schemes;
+ bool success = FALSE;
+
+ schemes = array_create(sizeof(signature_scheme_t), 0);
+ array_insert(schemes, ARRAY_TAIL, scheme);
+
+ keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
+ if (keymat->get_auth_octets(keymat, verify, this->ike_sa_init, this->nonce,
+ id, this->reserved, octets, schemes) &&
+ array_get(schemes, 0, &scheme))
+ {
+ success = TRUE;
+ }
+ array_destroy(schemes);
+ return success;
+}
+
+/**
* Create a classic IKEv2 signature
*/
static status_t sign_classic(private_pubkey_authenticator_t *this,
@@ -255,7 +282,6 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
chunk_t *auth_data)
{
signature_scheme_t scheme;
- keymat_v2_t *keymat;
chunk_t octets = chunk_empty;
status_t status = FAILED;
@@ -293,9 +319,7 @@ static status_t sign_classic(private_pubkey_authenticator_t *this,
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) &&
+ if (get_auth_octets_scheme(this, FALSE, id, &octets, &scheme) &&
private->sign(private, scheme, octets, auth_data))
{
status = SUCCESS;
@@ -363,7 +387,6 @@ METHOD(authenticator_t, process, status_t,
key_type_t key_type = KEY_ECDSA;
signature_scheme_t scheme;
status_t status = NOT_FOUND;
- keymat_v2_t *keymat;
const char *reason = "unsupported";
bool online;
@@ -402,9 +425,7 @@ METHOD(authenticator_t, process, status_t,
return INVALID_ARG;
}
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,
- this->nonce, id, this->reserved, &octets))
+ if (!get_auth_octets_scheme(this, TRUE, id, &octets, &scheme))
{
return FAILED;
}
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index 58efdbabe..70dacd1dc 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -629,7 +629,8 @@ METHOD(keymat_t, get_aead, aead_t*,
METHOD(keymat_v2_t, get_auth_octets, bool,
private_keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
- chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets)
+ chunk_t nonce, identification_t *id, char reserved[3], chunk_t *octets,
+ array_t *schemes)
{
chunk_t chunk, idx;
chunk_t skp;
@@ -669,7 +670,8 @@ METHOD(keymat_v2_t, get_psk_sig, bool,
{ /* EAP uses SK_p if no MSK has been established */
secret = verify ? this->skp_verify : this->skp_build;
}
- if (!get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved, &octets))
+ if (!get_auth_octets(this, verify, ike_sa_init, nonce, id, reserved,
+ &octets, NULL))
{
return FALSE;
}
diff --git a/src/libcharon/sa/ikev2/keymat_v2.h b/src/libcharon/sa/ikev2/keymat_v2.h
index 927b62b03..36bf149fe 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.h
+++ b/src/libcharon/sa/ikev2/keymat_v2.h
@@ -22,6 +22,7 @@
#define KEYMAT_V2_H_
#include <sa/keymat.h>
+#include <collections/array.h>
typedef struct keymat_v2_t keymat_v2_t;
@@ -100,11 +101,14 @@ struct keymat_v2_t {
* @param id identity
* @param reserved reserved bytes of id_payload
* @param octests chunk receiving allocated auth octets
+ * @param schemes array containing signature schemes in case they
+ * need to be modified by the keymat implementation
* @return TRUE if octets created successfully
*/
bool (*get_auth_octets)(keymat_v2_t *this, bool verify, chunk_t ike_sa_init,
chunk_t nonce, identification_t *id,
- char reserved[3], chunk_t *octets);
+ char reserved[3], chunk_t *octets,
+ array_t *schemes);
/**
* Build the shared secret signature used for PSK and EAP authentication.
*
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 60a262ffc..e4a16faf0 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -34,6 +34,7 @@
#include <sa/ikev2/tasks/ike_delete.h>
#include <sa/ikev2/tasks/ike_config.h>
#include <sa/ikev2/tasks/ike_dpd.h>
+#include <sa/ikev2/tasks/ike_mid_sync.h>
#include <sa/ikev2/tasks/ike_vendor.h>
#include <sa/ikev2/tasks/ike_verify_peer_cert.h>
#include <sa/ikev2/tasks/child_create.h>
@@ -817,7 +818,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
task_t *task;
message_t *message;
host_t *me, *other;
- bool delete = FALSE, hook = FALSE;
+ bool delete = FALSE, hook = FALSE, mid_sync = FALSE;
ike_sa_id_t *id = NULL;
uint64_t responder_spi = 0;
bool result;
@@ -836,6 +837,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
enumerator = array_create_enumerator(this->passive_tasks);
while (enumerator->enumerate(enumerator, (void*)&task))
{
+ if (task->get_type(task) == TASK_IKE_MID_SYNC)
+ {
+ mid_sync = TRUE;
+ }
switch (task->build(task, message))
{
case SUCCESS:
@@ -908,6 +913,15 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
}
return DESTROY_ME;
}
+ else if (mid_sync)
+ {
+ /* we don't want to resend messages to sync MIDs if requests with the
+ * previous MID arrive */
+ clear_packets(this->responding.packets);
+ /* avoid increasing the expected message ID after handling a message
+ * to sync MIDs with MID 0 */
+ return NEED_MORE;
+ }
array_compress(this->passive_tasks);
@@ -1069,6 +1083,10 @@ static status_t process_request(private_task_manager_t *this,
task = (task_t*)ike_redirect_create(
this->ike_sa, NULL);
break;
+ case IKEV2_MESSAGE_ID_SYNC:
+ task = (task_t*)ike_mid_sync_create(
+ this->ike_sa);
+ break;
default:
break;
}
@@ -1200,6 +1218,12 @@ METHOD(task_manager_t, incr_mid, void,
}
}
+METHOD(task_manager_t, get_mid, uint32_t,
+ private_task_manager_t *this, bool initiate)
+{
+ return initiate ? this->initiating.mid : this->responding.mid;
+}
+
/**
* Handle the given IKE fragment, if it is one.
*
@@ -1373,6 +1397,64 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg)
return status;
}
+/**
+ * Check if a message with message ID 0 looks like it is used to synchronize
+ * the message IDs.
+ */
+static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg,
+ bool strict)
+{
+ enumerator_t *enumerator;
+ notify_payload_t *notify;
+ payload_t *payload;
+ bool found = FALSE, other = FALSE;
+
+ if (msg->get_exchange_type(msg) == INFORMATIONAL)
+ {
+ enumerator = msg->create_payload_enumerator(msg);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) == PLV2_NOTIFY)
+ {
+ notify = (notify_payload_t*)payload;
+ switch (notify->get_notify_type(notify))
+ {
+ case IKEV2_MESSAGE_ID_SYNC:
+ case IPSEC_REPLAY_COUNTER_SYNC:
+ found = TRUE;
+ continue;
+ default:
+ break;
+ }
+ }
+ if (strict)
+ {
+ other = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found && !other;
+}
+
+/**
+ * Check if a message with message ID 0 looks like it is used to synchronize
+ * the message IDs and we are prepared to process it.
+ *
+ * Note: This is not called if the responder never sent a message before (i.e.
+ * we expect MID 0).
+ */
+static bool is_mid_sync(private_task_manager_t *this, message_t *msg)
+{
+ if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED &&
+ this->ike_sa->supports_extension(this->ike_sa,
+ EXT_IKE_MESSAGE_ID_SYNC))
+ {
+ return looks_like_mid_sync(this, msg, TRUE);
+ }
+ return FALSE;
+}
METHOD(task_manager_t, process_message, status_t,
private_task_manager_t *this, message_t *msg)
@@ -1421,7 +1503,7 @@ METHOD(task_manager_t, process_message, status_t,
mid = msg->get_message_id(msg);
if (msg->get_request(msg))
{
- if (mid == this->responding.mid)
+ if (mid == this->responding.mid || (mid == 0 && is_mid_sync(this, msg)))
{
/* reject initial messages if not received in specific states,
* after rekeying we only expect a DELETE in an INFORMATIONAL */
@@ -1462,7 +1544,8 @@ METHOD(task_manager_t, process_message, status_t,
}
}
else if ((mid == this->responding.mid - 1) &&
- array_count(this->responding.packets))
+ array_count(this->responding.packets) &&
+ !(mid == 0 && looks_like_mid_sync(this, msg, FALSE)))
{
status = handle_fragment(this, &this->responding.defrag, msg);
if (status != SUCCESS)
@@ -1477,7 +1560,7 @@ METHOD(task_manager_t, process_message, status_t,
}
else
{
- DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
mid, this->responding.mid);
}
}
@@ -1515,7 +1598,7 @@ METHOD(task_manager_t, process_message, status_t,
}
else
{
- DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored",
+ DBG1(DBG_IKE, "received message ID %d, expected %d, ignored",
mid, this->initiating.mid);
return SUCCESS;
}
@@ -2046,6 +2129,7 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa)
.initiate = _initiate,
.retransmit = _retransmit,
.incr_mid = _incr_mid,
+ .get_mid = _get_mid,
.reset = _reset,
.adopt_tasks = _adopt_tasks,
.adopt_child_tasks = _adopt_child_tasks,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 036910d0e..53daaf2ad 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -417,6 +417,9 @@ METHOD(task_t, build_i, status_t,
/* indicate support for EAP-only authentication */
message->add_notify(message, FALSE, EAP_ONLY_AUTHENTICATION,
chunk_empty);
+ /* indicate support for RFC 6311 Message ID synchronization */
+ message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
+ chunk_empty);
}
if (!this->do_another_auth && !this->my_auth)
@@ -466,7 +469,8 @@ METHOD(task_t, build_i, status_t,
get_reserved_id_bytes(this, id_payload);
message->add_payload(message, (payload_t*)id_payload);
- if (idr && message->get_message_id(message) == 1 &&
+ if (idr && !idr->contains_wildcards(idr) &&
+ message->get_message_id(message) == 1 &&
this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO &&
this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NEVER)
{
@@ -991,6 +995,10 @@ METHOD(task_t, process_i, status_t,
DBG1(DBG_IKE, "received invalid REDIRECT notify");
}
break;
+ case IKEV2_MESSAGE_ID_SYNC_SUPPORTED:
+ this->ike_sa->enable_extension(this->ike_sa,
+ EXT_IKE_MESSAGE_ID_SYNC);
+ break;
default:
{
if (type <= 16383)
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index d82e206b8..58b710616 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -159,6 +159,10 @@ static void send_supported_hash_algorithms(private_ike_init_t *this,
auth_cfg_t *auth;
auth_rule_t rule;
uintptr_t config;
+ int written;
+ size_t len = BUF_LEN;
+ char buf[len];
+ char *pos = buf;
char *plugin_name;
algos = hash_algorithm_set_create();
@@ -205,11 +209,23 @@ static void send_supported_hash_algorithms(private_ike_init_t *this,
while (enumerator->enumerate(enumerator, &hash))
{
writer->write_uint16(writer, hash);
+
+ /* generate debug output */
+ written = snprintf(pos, len, " %N", hash_algorithm_short_names,
+ hash);
+ if (written > 0 && written < len)
+ {
+ pos += written;
+ len -= written;
+ }
}
enumerator->destroy(enumerator);
message->add_notify(message, FALSE, SIGNATURE_HASH_ALGORITHMS,
writer->get_buf(writer));
writer->destroy(writer);
+
+ *pos = '\0';
+ DBG2(DBG_CFG, "sending supported signature hash algorithms:%s", buf);
}
algos->destroy(algos);
}
@@ -222,6 +238,10 @@ static void handle_supported_hash_algorithms(private_ike_init_t *this,
{
bio_reader_t *reader;
uint16_t algo;
+ int written;
+ size_t len = BUF_LEN;
+ char buf[len];
+ char *pos = buf;
bool added = FALSE;
reader = bio_reader_create(notify->get_notification_data(notify));
@@ -231,10 +251,22 @@ static void handle_supported_hash_algorithms(private_ike_init_t *this,
{
this->keymat->add_hash_algorithm(this->keymat, algo);
added = TRUE;
+
+ /* generate debug output */
+ written = snprintf(pos, len, " %N", hash_algorithm_short_names,
+ algo);
+ if (written > 0 && written < len)
+ {
+ pos += written;
+ len -= written;
+ }
}
}
reader->destroy(reader);
+ *pos = '\0';
+ DBG2(DBG_CFG, "received supported signature hash algorithms:%s", buf);
+
if (added)
{
this->ike_sa->enable_extension(this->ike_sa, EXT_SIGNATURE_AUTH);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c
new file mode 100644
index 000000000..24cf276f4
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+/*
+ * Copyright (C) 2016 Stephen J. Bevan
+ *
+ * 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.
+ */
+
+#include "ike_mid_sync.h"
+
+#include <daemon.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+#include <encoding/payloads/notify_payload.h>
+
+typedef struct private_ike_mid_sync_t private_ike_mid_sync_t;
+
+/**
+ * Private members
+ */
+struct private_ike_mid_sync_t {
+
+ /**
+ * Public methods and task_t interface.
+ */
+ ike_mid_sync_t public;
+
+ /**
+ * Assigned IKE_SA.
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * Nonce sent by the peer and expected to be returned
+ */
+ chunk_t nonce;
+
+ /**
+ * Expected next sender message ID
+ */
+ uint32_t send;
+
+ /**
+ * Expected received message ID
+ */
+ uint32_t recv;
+};
+
+/*
+ * Encoding of IKEV2_MESSAGE_SYNC_ID notify, RFC 6311
+ *
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Next Payload |C| RESERVED | Payload Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Protocol ID(=0)| SPI Size (=0) | Notify Message Type |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Nonce Data |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | EXPECTED_SEND_REQ_MESSAGE_ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | EXPECTED_RECV_REQ_MESSAGE_ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+/*
+ * RFC 6311 section 5.1
+ *
+ * o The peer MUST silently drop any received synchronization message
+ * if M1 is lower than or equal to the highest value it has seen from
+ * the cluster. This includes any previous received synchronization
+ * messages.
+ */
+METHOD(task_t, pre_process, status_t,
+ private_ike_mid_sync_t *this, message_t *message)
+{
+ notify_payload_t *notify;
+ bio_reader_t *reader;
+ chunk_t nonce;
+ uint32_t resp;
+
+ if (message->get_message_id(message) != 0)
+ { /* ignore the notify if it was contained in an INFORMATIONAL with
+ * unexpected message ID */
+ return SUCCESS;
+ }
+ if (!this->ike_sa->supports_extension(this->ike_sa,
+ EXT_IKE_MESSAGE_ID_SYNC))
+ {
+ DBG1(DBG_ENC, "unexpected %N notify, ignored", notify_type_names,
+ IKEV2_MESSAGE_ID_SYNC);
+ return FAILED;
+ }
+ notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC);
+
+ reader = bio_reader_create(notify->get_notification_data(notify));
+ if (!reader->read_data(reader, 4, &nonce) ||
+ !reader->read_uint32(reader, &this->send) ||
+ !reader->read_uint32(reader, &this->recv))
+ {
+ reader->destroy(reader);
+ DBG1(DBG_ENC, "received invalid %N notify",
+ notify_type_names, IKEV2_MESSAGE_ID_SYNC);
+ return FAILED;
+ }
+ reader->destroy(reader);
+ resp = this->ike_sa->get_message_id(this->ike_sa, FALSE);
+ if (this->send < resp)
+ {
+ DBG1(DBG_ENC, "ignore %N notify with lower (%d) than expected (%d) "
+ "sender MID", notify_type_names, IKEV2_MESSAGE_ID_SYNC, this->send,
+ resp);
+ return FAILED;
+ }
+ this->nonce = chunk_clone(nonce);
+ return SUCCESS;
+}
+
+/**
+ * Check if there are any active tasks, indicating that we already
+ * used the currents message ID and are waiting for a response.
+ */
+static bool has_active_tasks(private_ike_mid_sync_t *this)
+{
+ enumerator_t *enumerator;
+ task_t *task;
+ bool active;
+
+ enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
+ TASK_QUEUE_ACTIVE);
+ active = enumerator->enumerate(enumerator, &task);
+ enumerator->destroy(enumerator);
+ return active;
+}
+
+/*
+ * RFC 6311 section 5.1
+ *
+ * o M2 MUST be at least the higher of the received M1, and one more
+ * than the highest sender value received from the cluster. This
+ * includes any previous received synchronization messages.
+ *
+ * o P2 MUST be the higher of the received P1 value, and one more than
+ * the highest sender value used by the peer.
+ *
+ * M1 is this->send, P1 is this->recv
+ */
+METHOD(task_t, process, status_t,
+ private_ike_mid_sync_t *this, message_t *message)
+{
+ uint32_t resp, init, m2, p2;
+
+ if (message->get_message_id(message) != 0)
+ { /* ignore the notify if it was contained in an INFORMATIONAL with
+ * unexpected message id */
+ return SUCCESS;
+ }
+ resp = this->ike_sa->get_message_id(this->ike_sa, FALSE);
+ m2 = max(this->send, resp);
+ if (resp != m2)
+ {
+ this->ike_sa->set_message_id(this->ike_sa, FALSE, m2);
+ }
+ init = this->ike_sa->get_message_id(this->ike_sa, TRUE);
+ p2 = max(this->recv, has_active_tasks(this) ? init + 1 : init);
+ if (init != p2)
+ {
+ this->ike_sa->set_message_id(this->ike_sa, TRUE, p2);
+ }
+ DBG1(DBG_IKE, "responder requested MID sync: initiating %d[%d], "
+ "responding %d[%d]", p2, init, m2, resp);
+ this->send = p2;
+ this->recv = m2;
+ return NEED_MORE;
+}
+
+METHOD(task_t, build, status_t,
+ private_ike_mid_sync_t *this, message_t *message)
+{
+ bio_writer_t *writer;
+
+ writer = bio_writer_create(12);
+ writer->write_data(writer, this->nonce);
+ writer->write_uint32(writer, this->send);
+ writer->write_uint32(writer, this->recv);
+
+ message->set_message_id(message, 0);
+ message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC,
+ writer->get_buf(writer));
+
+ writer->destroy(writer);
+ return SUCCESS;
+}
+
+METHOD(task_t, get_type, task_type_t,
+ private_ike_mid_sync_t *this)
+{
+ return TASK_IKE_MID_SYNC;
+}
+
+METHOD(task_t, migrate, void,
+ private_ike_mid_sync_t *this, ike_sa_t *ike_sa)
+{
+ this->ike_sa = ike_sa;
+ chunk_free(&this->nonce);
+}
+
+METHOD(task_t, destroy, void,
+ private_ike_mid_sync_t *this)
+{
+ chunk_free(&this->nonce);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+ike_mid_sync_t *ike_mid_sync_create(ike_sa_t *ike_sa)
+{
+ private_ike_mid_sync_t *this;
+
+ INIT(this,
+ .public = {
+ .task = {
+ .get_type = _get_type,
+ .build = _build,
+ .pre_process = _pre_process,
+ .process = _process,
+ .migrate = _migrate,
+ .destroy = _destroy,
+ },
+ },
+ .ike_sa = ike_sa,
+ );
+ return &this->public;
+}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h
new file mode 100644
index 000000000..9dd46f925
--- /dev/null
+++ b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+/*
+ * Copyright (C) 2016 Stephen J. Bevan
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup ike_mid_sync ike_mid_sync
+ * @{ @ingroup tasks_v2
+ */
+
+#ifndef IKE_MID_SYNC_H_
+#define IKE_MID_SYNC_H_
+
+typedef struct ike_mid_sync_t ike_mid_sync_t;
+
+#include <library.h>
+#include <sa/ike_sa.h>
+#include <sa/task.h>
+
+/**
+ * Task of type TASK_IKE_MID_SYNC, implements RFC 6311 responder.
+ *
+ * This task handles an IKEV2_MESSAGE_ID_SYNC notify sent by a peer
+ * and if acceptable updates the SA MIDs and replies with the updated
+ * MID values.
+ */
+struct ike_mid_sync_t {
+
+ /**
+ * Implements the task_t interface
+ */
+ task_t task;
+};
+
+/**
+ * Create a new TASK_IKE_MID_SYNC task.
+ *
+ * @param ike_sa IKE_SA this task works for
+ * @return task to handle by the task_manager
+ */
+ike_mid_sync_t *ike_mid_sync_create(ike_sa_t *ike_sa);
+
+#endif /** IKE_MID_SYNC_H_ @}*/
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 40e291be5..b0162751d 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -36,7 +36,7 @@ struct private_shunt_manager_t {
shunt_manager_t public;
/**
- * Installed shunts, as child_cfg_t
+ * Installed shunts, as entry_t
*/
linked_list_t *shunts;
@@ -57,6 +57,32 @@ struct private_shunt_manager_t {
};
/**
+ * Config entry for a shunt
+ */
+typedef struct {
+ /**
+ * Configured namespace
+ */
+ char *ns;
+
+ /**
+ * Child config
+ */
+ child_cfg_t *cfg;
+
+} entry_t;
+
+/**
+ * Destroy a config entry
+ */
+static void entry_destroy(entry_t *this)
+{
+ this->cfg->destroy(this->cfg);
+ free(this->ns);
+ free(this);
+}
+
+/**
* Install in and out shunt policies in the kernel
*/
static bool install_shunt_policy(child_cfg_t *child)
@@ -162,10 +188,10 @@ static bool install_shunt_policy(child_cfg_t *child)
}
METHOD(shunt_manager_t, install, bool,
- private_shunt_manager_t *this, child_cfg_t *child)
+ private_shunt_manager_t *this, char *ns, child_cfg_t *cfg)
{
enumerator_t *enumerator;
- child_cfg_t *child_cfg;
+ entry_t *entry;
bool found = FALSE, success;
/* check if not already installed */
@@ -176,9 +202,10 @@ METHOD(shunt_manager_t, install, bool,
return FALSE;
}
enumerator = this->shunts->create_enumerator(this->shunts);
- while (enumerator->enumerate(enumerator, &child_cfg))
+ while (enumerator->enumerate(enumerator, &entry))
{
- if (streq(child_cfg->get_name(child_cfg), child->get_name(child)))
+ if (streq(ns, entry->ns) &&
+ streq(cfg->get_name(cfg), entry->cfg->get_name(entry->cfg)))
{
found = TRUE;
break;
@@ -188,21 +215,25 @@ METHOD(shunt_manager_t, install, bool,
if (found)
{
DBG1(DBG_CFG, "shunt %N policy '%s' already installed",
- ipsec_mode_names, child->get_mode(child), child->get_name(child));
+ ipsec_mode_names, cfg->get_mode(cfg), cfg->get_name(cfg));
this->lock->unlock(this->lock);
return TRUE;
}
- this->shunts->insert_last(this->shunts, child->get_ref(child));
+ INIT(entry,
+ .ns = strdupnull(ns),
+ .cfg = cfg->get_ref(cfg),
+ );
+ this->shunts->insert_last(this->shunts, entry);
this->installing++;
this->lock->unlock(this->lock);
- success = install_shunt_policy(child);
+ success = install_shunt_policy(cfg);
this->lock->write_lock(this->lock);
if (!success)
{
- this->shunts->remove(this->shunts, child, NULL);
- child->destroy(child);
+ this->shunts->remove(this->shunts, entry, NULL);
+ entry_destroy(entry);
}
this->installing--;
this->condvar->signal(this->condvar);
@@ -320,19 +351,20 @@ static void uninstall_shunt_policy(child_cfg_t *child)
}
METHOD(shunt_manager_t, uninstall, bool,
- private_shunt_manager_t *this, char *name)
+ private_shunt_manager_t *this, char *ns, char *name)
{
enumerator_t *enumerator;
- child_cfg_t *child, *found = NULL;
+ entry_t *entry, *found = NULL;
this->lock->write_lock(this->lock);
enumerator = this->shunts->create_enumerator(this->shunts);
- while (enumerator->enumerate(enumerator, &child))
+ while (enumerator->enumerate(enumerator, &entry))
{
- if (streq(name, child->get_name(child)))
+ if (streq(ns, entry->ns) &&
+ streq(name, entry->cfg->get_name(entry->cfg)))
{
this->shunts->remove_at(this->shunts, enumerator);
- found = child;
+ found = entry;
break;
}
}
@@ -343,8 +375,19 @@ METHOD(shunt_manager_t, uninstall, bool,
{
return FALSE;
}
- uninstall_shunt_policy(child);
- child->destroy(child);
+ uninstall_shunt_policy(found->cfg);
+ entry_destroy(found);
+ return TRUE;
+}
+
+CALLBACK(filter_entries, bool,
+ void *unused, entry_t **entry, char **ns, void **in, child_cfg_t **cfg)
+{
+ if (ns)
+ {
+ *ns = (*entry)->ns;
+ }
+ *cfg = (*entry)->cfg;
return TRUE;
}
@@ -352,25 +395,26 @@ METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
private_shunt_manager_t *this)
{
this->lock->read_lock(this->lock);
- return enumerator_create_cleaner(
+ return enumerator_create_filter(
this->shunts->create_enumerator(this->shunts),
- (void*)this->lock->unlock, this->lock);
+ (void*)filter_entries, this->lock,
+ (void*)this->lock->unlock);
}
METHOD(shunt_manager_t, flush, void,
private_shunt_manager_t *this)
{
- child_cfg_t *child;
+ entry_t *entry;
this->lock->write_lock(this->lock);
while (this->installing)
{
this->condvar->wait(this->condvar, this->lock);
}
- while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
+ while (this->shunts->remove_last(this->shunts, (void**)&entry) == SUCCESS)
{
- uninstall_shunt_policy(child);
- child->destroy(child);
+ uninstall_shunt_policy(entry->cfg);
+ entry_destroy(entry);
}
this->installing = INSTALL_DISABLED;
this->lock->unlock(this->lock);
diff --git a/src/libcharon/sa/shunt_manager.h b/src/libcharon/sa/shunt_manager.h
index c43f5db3d..f2b721032 100644
--- a/src/libcharon/sa/shunt_manager.h
+++ b/src/libcharon/sa/shunt_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Tobias Brunner
+ * Copyright (C) 2015-2016 Tobias Brunner
* Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -36,23 +36,26 @@ struct shunt_manager_t {
/**
* Install a policy as a shunt.
*
- * @param child child configuration to install as a shunt
+ * @param ns optional namespace (e.g. name of a connection or
+ * plugin), cloned
+ * @param child child configuration to install as a shunt
* @return TRUE if installed successfully
*/
- bool (*install)(shunt_manager_t *this, child_cfg_t *child);
+ bool (*install)(shunt_manager_t *this, char *ns, child_cfg_t *child);
/**
* Uninstall a shunt policy.
*
+ * @param ns namespace (same as given during installation)
* @param name name of child configuration to uninstall as a shunt
* @return TRUE if uninstalled successfully
*/
- bool (*uninstall)(shunt_manager_t *this, char *name);
+ bool (*uninstall)(shunt_manager_t *this, char *ns, char *name);
/**
* Create an enumerator over all installed shunts.
*
- * @return enumerator over (child_sa_t)
+ * @return enumerator over (char*, child_cfg_t*)
*/
enumerator_t* (*create_enumerator)(shunt_manager_t *this);
diff --git a/src/libcharon/sa/task.c b/src/libcharon/sa/task.c
index 405eda66b..30de08c9b 100644
--- a/src/libcharon/sa/task.c
+++ b/src/libcharon/sa/task.c
@@ -30,6 +30,7 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST,
"IKE_REAUTH_COMPLETE",
"IKE_REDIRECT",
"IKE_VERIFY_PEER_CERT",
+ "IKE_MID_SYNC",
"IKE_DELETE",
"IKE_DPD",
"IKE_VENDOR",
diff --git a/src/libcharon/sa/task.h b/src/libcharon/sa/task.h
index 31d70fb3b..5f77149ba 100644
--- a/src/libcharon/sa/task.h
+++ b/src/libcharon/sa/task.h
@@ -61,6 +61,8 @@ enum task_type_t {
TASK_IKE_REDIRECT,
/** verify a peer's certificate */
TASK_IKE_VERIFY_PEER_CERT,
+ /** synchronize message IDs, RFC6311 */
+ TASK_IKE_MID_SYNC,
/** delete an IKE_SA */
TASK_IKE_DELETE,
/** liveness check */
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 86077d373..7e9262291 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -240,6 +240,14 @@ struct task_manager_t {
void (*incr_mid)(task_manager_t *this, bool initiate);
/**
+ * Get the current message ID counter, in- or outbound.
+ *
+ * @param initiate TRUE to get the initiating ID
+ * @return current message ID
+ */
+ uint32_t (*get_mid)(task_manager_t *this, bool initiate);
+
+ /**
* Reset message ID counters of the task manager.
*
* The IKEv2 protocol requires to restart exchanges with message IDs
@@ -253,7 +261,7 @@ struct task_manager_t {
* @param initiate message ID / DPD seq to initiate exchanges (send)
* @param respond message ID / DPD seq to respond to exchanges (expect)
*/
- void (*reset) (task_manager_t *this, uint32_t initiate, uint32_t respond);
+ void (*reset)(task_manager_t *this, uint32_t initiate, uint32_t respond);
/**
* Check if we are currently waiting for a reply.
diff --git a/src/libcharon/tests/Makefile.am b/src/libcharon/tests/Makefile.am
index b8670246b..8f762a2e6 100644
--- a/src/libcharon/tests/Makefile.am
+++ b/src/libcharon/tests/Makefile.am
@@ -29,6 +29,7 @@ exchange_tests_SOURCES = \
suites/test_child_delete.c \
suites/test_child_rekey.c \
suites/test_ike_delete.c \
+ suites/test_ike_mid_sync.c \
suites/test_ike_rekey.c \
utils/exchange_test_asserts.h utils/exchange_test_asserts.c \
utils/exchange_test_helper.h utils/exchange_test_helper.c \
diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in
index 7b6beae24..e922a7171 100644
--- a/src/libcharon/tests/Makefile.in
+++ b/src/libcharon/tests/Makefile.in
@@ -115,6 +115,7 @@ am_exchange_tests_OBJECTS = \
suites/exchange_tests-test_child_delete.$(OBJEXT) \
suites/exchange_tests-test_child_rekey.$(OBJEXT) \
suites/exchange_tests-test_ike_delete.$(OBJEXT) \
+ suites/exchange_tests-test_ike_mid_sync.$(OBJEXT) \
suites/exchange_tests-test_ike_rekey.$(OBJEXT) \
utils/exchange_tests-exchange_test_asserts.$(OBJEXT) \
utils/exchange_tests-exchange_test_helper.$(OBJEXT) \
@@ -381,7 +382,6 @@ 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@
@@ -416,6 +416,7 @@ nm_LIBS = @nm_LIBS@
nm_ca_dir = @nm_ca_dir@
nm_plugins = @nm_plugins@
oldincludedir = @oldincludedir@
+p_plugins = @p_plugins@
pcsclite_CFLAGS = @pcsclite_CFLAGS@
pcsclite_LIBS = @pcsclite_LIBS@
pdfdir = @pdfdir@
@@ -491,6 +492,7 @@ exchange_tests_SOURCES = \
suites/test_child_delete.c \
suites/test_child_rekey.c \
suites/test_ike_delete.c \
+ suites/test_ike_mid_sync.c \
suites/test_ike_rekey.c \
utils/exchange_test_asserts.h utils/exchange_test_asserts.c \
utils/exchange_test_helper.h utils/exchange_test_helper.c \
@@ -572,6 +574,8 @@ suites/exchange_tests-test_child_rekey.$(OBJEXT): \
suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
suites/exchange_tests-test_ike_delete.$(OBJEXT): \
suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
+suites/exchange_tests-test_ike_mid_sync.$(OBJEXT): \
+ suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
suites/exchange_tests-test_ike_rekey.$(OBJEXT): \
suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
utils/$(am__dirstamp):
@@ -623,6 +627,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/exchange_tests-test_child_delete.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/exchange_tests-test_child_rekey.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/exchange_tests-test_ike_delete.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/exchange_tests-test_ike_rekey.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po@am__quote@
@@ -715,6 +720,20 @@ suites/exchange_tests-test_ike_delete.obj: suites/test_ike_delete.c
@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) $(exchange_tests_CFLAGS) $(CFLAGS) -c -o suites/exchange_tests-test_ike_delete.obj `if test -f 'suites/test_ike_delete.c'; then $(CYGPATH_W) 'suites/test_ike_delete.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ike_delete.c'; fi`
+suites/exchange_tests-test_ike_mid_sync.o: suites/test_ike_mid_sync.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(exchange_tests_CFLAGS) $(CFLAGS) -MT suites/exchange_tests-test_ike_mid_sync.o -MD -MP -MF suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Tpo -c -o suites/exchange_tests-test_ike_mid_sync.o `test -f 'suites/test_ike_mid_sync.c' || echo '$(srcdir)/'`suites/test_ike_mid_sync.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Tpo suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ike_mid_sync.c' object='suites/exchange_tests-test_ike_mid_sync.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) $(exchange_tests_CFLAGS) $(CFLAGS) -c -o suites/exchange_tests-test_ike_mid_sync.o `test -f 'suites/test_ike_mid_sync.c' || echo '$(srcdir)/'`suites/test_ike_mid_sync.c
+
+suites/exchange_tests-test_ike_mid_sync.obj: suites/test_ike_mid_sync.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(exchange_tests_CFLAGS) $(CFLAGS) -MT suites/exchange_tests-test_ike_mid_sync.obj -MD -MP -MF suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Tpo -c -o suites/exchange_tests-test_ike_mid_sync.obj `if test -f 'suites/test_ike_mid_sync.c'; then $(CYGPATH_W) 'suites/test_ike_mid_sync.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ike_mid_sync.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Tpo suites/$(DEPDIR)/exchange_tests-test_ike_mid_sync.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ike_mid_sync.c' object='suites/exchange_tests-test_ike_mid_sync.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) $(exchange_tests_CFLAGS) $(CFLAGS) -c -o suites/exchange_tests-test_ike_mid_sync.obj `if test -f 'suites/test_ike_mid_sync.c'; then $(CYGPATH_W) 'suites/test_ike_mid_sync.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ike_mid_sync.c'; fi`
+
suites/exchange_tests-test_ike_rekey.o: suites/test_ike_rekey.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(exchange_tests_CFLAGS) $(CFLAGS) -MT suites/exchange_tests-test_ike_rekey.o -MD -MP -MF suites/$(DEPDIR)/exchange_tests-test_ike_rekey.Tpo -c -o suites/exchange_tests-test_ike_rekey.o `test -f 'suites/test_ike_rekey.c' || echo '$(srcdir)/'`suites/test_ike_rekey.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/exchange_tests-test_ike_rekey.Tpo suites/$(DEPDIR)/exchange_tests-test_ike_rekey.Po
diff --git a/src/libcharon/tests/exchange_tests.h b/src/libcharon/tests/exchange_tests.h
index 30086721f..6b35ea5e5 100644
--- a/src/libcharon/tests/exchange_tests.h
+++ b/src/libcharon/tests/exchange_tests.h
@@ -14,6 +14,7 @@
*/
TEST_SUITE(ike_delete_suite_create)
+TEST_SUITE(ike_mid_sync_suite_create)
TEST_SUITE(ike_rekey_suite_create)
TEST_SUITE(child_create_suite_create)
TEST_SUITE(child_delete_suite_create)
diff --git a/src/libcharon/tests/libcharon_tests.c b/src/libcharon/tests/libcharon_tests.c
index 1ef13e978..3fe5b0e90 100644
--- a/src/libcharon/tests/libcharon_tests.c
+++ b/src/libcharon/tests/libcharon_tests.c
@@ -45,7 +45,7 @@ static void initialize_logging()
lib->settings->set_int(lib->settings, "%s.filelog.stderr.default",
lib->settings->get_int(lib->settings, "%s.filelog.stderr.default",
level, lib->ns), lib->ns);
- charon->load_loggers(charon, NULL, TRUE);
+ charon->load_loggers(charon);
}
static bool test_runner_init(bool init)
diff --git a/src/libcharon/tests/suites/test_ike_mid_sync.c b/src/libcharon/tests/suites/test_ike_mid_sync.c
new file mode 100644
index 000000000..3776f39e9
--- /dev/null
+++ b/src/libcharon/tests/suites/test_ike_mid_sync.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2016 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <tests/utils/exchange_test_helper.h>
+#include <tests/utils/exchange_test_asserts.h>
+#include <tests/utils/sa_asserts.h>
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+/**
+ * FIXME: Since we don't have the server side yet, this is kind of a hack!!!
+ */
+
+/**
+ * Add the IKEV2_MESSAGE_ID_SYNC_SUPPORTED notify to the IKE_AUTH response
+ */
+static bool add_notify(listener_t *listener, ike_sa_t *ike_sa,
+ message_t *message, bool incoming, bool plain)
+{
+ if (plain && !incoming && message->get_exchange_type(message) == IKE_AUTH &&
+ !message->get_request(message))
+ {
+ message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC_SUPPORTED,
+ chunk_empty);
+ return FALSE;
+ }
+ return TRUE;
+}
+#define add_notify_to_ike_auth() ({ \
+ listener_t _notify_listener = { \
+ .message = add_notify, \
+ }; \
+ exchange_test_helper->add_listener(exchange_test_helper, &_notify_listener); \
+})
+
+/**
+ * Handle IKEV2_MESSAGE_ID_SYNC notifies
+ */
+typedef struct {
+ listener_t listener;
+ struct {
+ chunk_t nonce;
+ uint32_t send;
+ uint32_t recv;
+ } init, resp;
+} mid_sync_listener_t;
+
+static bool handle_mid(listener_t *listener,
+ ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
+{
+ mid_sync_listener_t *this = (mid_sync_listener_t*)listener;
+
+ if (!plain || incoming)
+ {
+ return TRUE;
+ }
+
+ if (message->get_exchange_type(message) == INFORMATIONAL)
+ {
+ if (streq("resp", ike_sa->get_name(ike_sa)))
+ {
+ bio_writer_t *writer;
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ ignore_result(rng->allocate_bytes(rng, 4, &this->init.nonce));
+ rng->destroy(rng);
+ writer = bio_writer_create(12);
+ writer->write_data(writer, this->init.nonce);
+ writer->write_uint32(writer, this->init.send);
+ writer->write_uint32(writer, this->init.recv);
+ message->set_message_id(message, 0);
+ message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC,
+ writer->get_buf(writer));
+ writer->destroy(writer);
+ }
+ else
+ {
+ notify_payload_t *notify;
+ bio_reader_t *reader;
+
+ notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC);
+ reader = bio_reader_create(notify->get_notification_data(notify));
+ chunk_clear(&this->resp.nonce);
+ reader->read_data(reader, 4, &this->resp.nonce);
+ this->resp.nonce = chunk_clone(this->resp.nonce);
+ reader->read_uint32(reader, &this->resp.send);
+ reader->read_uint32(reader, &this->resp.recv);
+ reader->destroy(reader);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Send a MESSAGE_ID_SYNC notify in an INFORMATIONAL. We reset the state
+ * afterwards so this seems as if nothing happened.
+ */
+static void send_mid_sync(ike_sa_t *sa, uint32_t send, uint32_t recv)
+{
+ call_ikesa(sa, send_dpd);
+ sa->set_message_id(sa, TRUE, send);
+ sa->set_message_id(sa, FALSE, recv);
+ sa->flush_queue(sa, TASK_QUEUE_QUEUED);
+}
+
+/**
+ * Send a regular DPD from one IKE_SA to another
+ */
+static void send_dpd(ike_sa_t *from, ike_sa_t *to)
+{
+ uint32_t send, recv;
+
+ send = from->get_message_id(from, TRUE);
+ recv = to->get_message_id(to, FALSE);
+ call_ikesa(from, send_dpd);
+ exchange_test_helper->process_message(exchange_test_helper, to, NULL);
+ exchange_test_helper->process_message(exchange_test_helper, from, NULL);
+ ck_assert_int_eq(send + 1, from->get_message_id(from, TRUE));
+ ck_assert_int_eq(recv + 1, to->get_message_id(to, FALSE));
+}
+
+/**
+ * Send a number of DPDs from on IKE_SA to the other
+ */
+static void send_dpds(ike_sa_t *from, ike_sa_t *to, int count)
+{
+ while (count--)
+ {
+ send_dpd(from, to);
+ }
+}
+
+static struct {
+ int dpds_a, dpds_b;
+ uint32_t send, recv;
+} data[] = {
+ { 0, 0, 0, 2 },
+ { 0, 0, 1, 3 },
+ { 1, 0, 0, 3 },
+ { 1, 0, 5, 8 },
+ { 0, 1, 1, 2 },
+ { 0, 1, 2, 2 },
+ { 1, 1, 1, 3 },
+ { 1, 1, 2, 4 },
+ { 1, 2, 2, 4 },
+};
+
+/**
+ * The responder syncs message IDs with the initiator
+ */
+START_TEST(test_responder)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data[_i].send,
+ .recv = data[_i].recv,
+ },
+ };
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data[_i].dpds_a);
+ send_dpds(b, a, data[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data[_i].send, data[_i].recv);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
+ ck_assert_int_eq(data[_i].recv, mid.resp.send);
+ ck_assert_int_eq(data[_i].send, mid.resp.recv);
+ ck_assert_int_eq(data[_i].recv, a->get_message_id(a, TRUE));
+ ck_assert_int_eq(data[_i].send, a->get_message_id(a, FALSE));
+ /* this currently won't be handled */
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+/**
+ * Make sure a retransmit is handled properly.
+ */
+START_TEST(test_retransmit)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data[_i].send,
+ .recv = data[_i].recv,
+ },
+ };
+ message_t *msg, *retransmit;
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data[_i].dpds_a);
+ send_dpds(b, a, data[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data[_i].send, data[_i].recv);
+ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
+ retransmit = message_create_from_packet(msg->get_packet(msg));
+ retransmit->parse_header(retransmit);
+ exchange_test_helper->process_message(exchange_test_helper, a, msg);
+ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
+ msg->destroy(msg);
+ exchange_test_helper->process_message(exchange_test_helper, a, retransmit);
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+/**
+ * Make sure a replayed or delayed notify is ignored.
+ */
+START_TEST(test_replay)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data[_i].send,
+ .recv = data[_i].recv,
+ },
+ };
+ message_t *msg, *replay;
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data[_i].dpds_a);
+ send_dpds(b, a, data[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data[_i].send, data[_i].recv);
+ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
+ replay = message_create_from_packet(msg->get_packet(msg));
+ replay->parse_header(replay);
+ exchange_test_helper->process_message(exchange_test_helper, a, msg);
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ exchange_test_helper->process_message(exchange_test_helper, a, replay);
+ ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+/**
+ * Make sure the notify is ignored if the extension is not enabled.
+ */
+START_TEST(test_disabled)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data[_i].send,
+ .recv = data[_i].recv,
+ },
+ };
+
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data[_i].dpds_a);
+ send_dpds(b, a, data[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data[_i].dpds_b, UINT_MAX);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ /* we don't expect a response and unchanged MIDs */
+ ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
+ ck_assert_int_eq(2 + data[_i].dpds_a, a->get_message_id(a, TRUE));
+ ck_assert_int_eq(data[_i].dpds_b, a->get_message_id(a, FALSE));
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+static struct {
+ int dpds_a, dpds_b;
+ uint32_t send, recv;
+} data_too_low[] = {
+ { 0, 1, 0, 2 },
+ { 1, 2, 0, 0 },
+ { 1, 2, 1, 3 },
+};
+
+/**
+ * The responder syncs message IDs with the initiator but uses too low sender
+ * MIDs so the initiator ignores the notify.
+ */
+START_TEST(test_sender_too_low)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data_too_low[_i].send,
+ .recv = data_too_low[_i].recv,
+ },
+ };
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data_too_low[_i].dpds_a);
+ send_dpds(b, a, data_too_low[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data_too_low[_i].dpds_b, UINT_MAX);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ /* we don't expect a response and unchanged MIDs */
+ ck_assert(!exchange_test_helper->sender->dequeue(exchange_test_helper->sender));
+ ck_assert_int_eq(2 + data_too_low[_i].dpds_a, a->get_message_id(a, TRUE));
+ ck_assert_int_eq(data_too_low[_i].dpds_b, a->get_message_id(a, FALSE));
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+}
+END_TEST
+
+static struct {
+ int dpds_a, dpds_b;
+ uint32_t send, recv;
+ /* reversed so the table below is clearer */
+ uint32_t recv_exp, send_exp;
+} data_recv_update[] = {
+ { 0, 0, 0, 0, 0, 2 },
+ { 0, 0, 0, 1, 0, 2 },
+ { 0, 0, 1, 1, 1, 2 },
+ { 1, 0, 0, 1, 0, 3 },
+ { 1, 0, 5, 2, 5, 3 },
+};
+
+/**
+ * The responder syncs message IDs with the initiator but uses too low receiver
+ * MID, which is updated by the initiator in the response.
+ */
+START_TEST(test_recv_update)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data_recv_update[_i].send,
+ .recv = data_recv_update[_i].recv,
+ },
+ };
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data_recv_update[_i].dpds_a);
+ send_dpds(b, a, data_recv_update[_i].dpds_b);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data_recv_update[_i].send, data_recv_update[_i].recv);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
+ ck_assert_int_eq(data_recv_update[_i].send_exp, mid.resp.send);
+ ck_assert_int_eq(data_recv_update[_i].recv_exp, mid.resp.recv);
+ ck_assert_int_eq(data_recv_update[_i].send_exp, a->get_message_id(a, TRUE));
+ ck_assert_int_eq(data_recv_update[_i].recv_exp, a->get_message_id(a, FALSE));
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+ /* fake the receipt of the notify */
+ b->set_message_id(b, TRUE, data_recv_update[_i].recv_exp);
+ b->set_message_id(b, FALSE, data_recv_update[_i].send_exp);
+
+ send_dpd(a, b);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+static struct {
+ int dpds_a, dpds_b;
+ uint32_t send, recv;
+ /* reversed so the table below is clearer */
+ uint32_t recv_exp, send_exp;
+} data_active[] = {
+ { 0, 0, 0, 2, 0, 3 },
+ { 0, 0, 1, 3, 1, 3 },
+ { 1, 0, 0, 3, 0, 4 },
+ { 1, 0, 5, 8, 5, 8 },
+ { 0, 1, 1, 2, 1, 3 },
+ { 0, 1, 2, 2, 2, 2 },
+ { 1, 1, 1, 3, 1, 4 },
+ { 1, 1, 2, 4, 2, 4 },
+};
+
+/**
+ * The responder syncs message IDs with the initiator that waits for the
+ * response for an active task.
+ */
+START_TEST(test_active)
+{
+ ike_sa_t *a, *b;
+ mid_sync_listener_t mid = {
+ .listener = { .message = (void*)handle_mid, },
+ .init = {
+ .send = data_active[_i].send,
+ .recv = data_active[_i].recv,
+ },
+ };
+ message_t *msg;
+
+ add_notify_to_ike_auth();
+ exchange_test_helper->establish_sa(exchange_test_helper,
+ &a, &b, NULL);
+
+ send_dpds(a, b, data_active[_i].dpds_a);
+ send_dpds(b, a, data_active[_i].dpds_b);
+
+ call_ikesa(a, send_dpd);
+ msg = exchange_test_helper->sender->dequeue(exchange_test_helper->sender);
+ msg->destroy(msg);
+
+ exchange_test_helper->add_listener(exchange_test_helper, &mid.listener);
+ send_mid_sync(b, data_active[_i].recv_exp, data_active[_i].send_exp);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ ck_assert_chunk_eq(mid.init.nonce, mid.resp.nonce);
+ ck_assert_int_eq(data_active[_i].send_exp, mid.resp.send);
+ ck_assert_int_eq(data_active[_i].recv_exp, mid.resp.recv);
+ ck_assert_int_eq(data_active[_i].send_exp, a->get_message_id(a, TRUE));
+ ck_assert_int_eq(data_active[_i].recv_exp, a->get_message_id(a, FALSE));
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ charon->bus->remove_listener(charon->bus, &mid.listener);
+
+ /* the active task was queued again */
+ call_ikesa(a, initiate, NULL, 0, NULL, NULL);
+ exchange_test_helper->process_message(exchange_test_helper, b, NULL);
+ exchange_test_helper->process_message(exchange_test_helper, a, NULL);
+ send_dpd(b, a);
+
+ call_ikesa(a, destroy);
+ call_ikesa(b, destroy);
+ chunk_free(&mid.init.nonce);
+ chunk_free(&mid.resp.nonce);
+}
+END_TEST
+
+Suite *ike_mid_sync_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("ike MID sync");
+
+ tc = tcase_create("responder");
+ tcase_add_loop_test(tc, test_responder, 0, countof(data));
+ tcase_add_loop_test(tc, test_retransmit, 0, countof(data));
+ tcase_add_loop_test(tc, test_replay, 0, countof(data));
+ tcase_add_loop_test(tc, test_disabled, 0, countof(data));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("sender MID too low");
+ tcase_add_loop_test(tc, test_sender_too_low, 0, countof(data_too_low));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("receiver MID updated");
+ tcase_add_loop_test(tc, test_recv_update, 0, countof(data_recv_update));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("active task");
+ tcase_add_loop_test(tc, test_active, 0, countof(data_active));
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/tests/suites/test_proposal.c b/src/libcharon/tests/suites/test_proposal.c
index 19f4cd1e1..f1591794a 100644
--- a/src/libcharon/tests/suites/test_proposal.c
+++ b/src/libcharon/tests/suites/test_proposal.c
@@ -108,7 +108,7 @@ START_TEST(test_select)
select_data[_i].self);
other = proposal_create_from_string(select_data[_i].proto,
select_data[_i].other);
- selected = self->select(self, other, FALSE);
+ selected = self->select(self, other, TRUE, FALSE);
if (select_data[_i].expected)
{
expected = proposal_create_from_string(select_data[_i].proto,
@@ -128,6 +128,29 @@ START_TEST(test_select)
}
END_TEST
+START_TEST(test_select_spi)
+{
+ proposal_t *self, *other, *selected;
+
+ self = proposal_create_from_string(PROTO_ESP, "aes128-sha256-modp3072");
+ other = proposal_create_from_string(PROTO_ESP, "aes128-sha256-modp3072");
+ other->set_spi(other, 0x12345678);
+
+ selected = self->select(self, other, TRUE, FALSE);
+ ck_assert(selected);
+ ck_assert_int_eq(selected->get_spi(selected), other->get_spi(other));
+ selected->destroy(selected);
+
+ selected = self->select(self, other, FALSE, FALSE);
+ ck_assert(selected);
+ ck_assert_int_eq(selected->get_spi(selected), self->get_spi(self));
+ selected->destroy(selected);
+
+ other->destroy(other);
+ self->destroy(self);
+}
+END_TEST
+
Suite *proposal_suite_create()
{
Suite *s;
@@ -141,6 +164,7 @@ Suite *proposal_suite_create()
tc = tcase_create("select");
tcase_add_loop_test(tc, test_select, 0, countof(select_data));
+ tcase_add_test(tc, test_select_spi);
suite_add_tcase(s, tc);
return s;
diff --git a/src/libcharon/tests/utils/exchange_test_helper.c b/src/libcharon/tests/utils/exchange_test_helper.c
index f32906d5d..fce0ccedf 100644
--- a/src/libcharon/tests/utils/exchange_test_helper.c
+++ b/src/libcharon/tests/utils/exchange_test_helper.c
@@ -282,7 +282,7 @@ static void initialize_logging()
level, lib->ns), lib->ns);
lib->settings->set_bool(lib->settings, "%s.filelog.stderr.ike_name", TRUE,
lib->ns);
- charon->load_loggers(charon, NULL, TRUE);
+ charon->load_loggers(charon);
}
/**