summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Android.mk17
-rw-r--r--src/libcharon/Makefile.am34
-rw-r--r--src/libcharon/Makefile.in251
-rw-r--r--src/libcharon/bus/bus.c212
-rw-r--r--src/libcharon/bus/bus.h42
-rw-r--r--src/libcharon/bus/listeners/file_logger.c32
-rw-r--r--src/libcharon/bus/listeners/file_logger.h7
-rw-r--r--src/libcharon/bus/listeners/listener.h19
-rw-r--r--src/libcharon/bus/listeners/sys_logger.c1
-rw-r--r--src/libcharon/bus/listeners/sys_logger.h2
-rw-r--r--src/libcharon/config/auth_cfg.c768
-rw-r--r--src/libcharon/config/auth_cfg.h201
-rw-r--r--src/libcharon/config/child_cfg.c58
-rw-r--r--src/libcharon/config/child_cfg.h34
-rw-r--r--src/libcharon/config/peer_cfg.h2
-rw-r--r--src/libcharon/credentials/credential_manager.c1681
-rw-r--r--src/libcharon/credentials/credential_manager.h203
-rw-r--r--src/libcharon/credentials/credential_set.h108
-rw-r--r--src/libcharon/credentials/sets/auth_cfg_wrapper.c223
-rw-r--r--src/libcharon/credentials/sets/auth_cfg_wrapper.h53
-rw-r--r--src/libcharon/credentials/sets/cert_cache.c390
-rw-r--r--src/libcharon/credentials/sets/cert_cache.h71
-rw-r--r--src/libcharon/credentials/sets/ocsp_response_wrapper.c147
-rw-r--r--src/libcharon/credentials/sets/ocsp_response_wrapper.h53
-rw-r--r--src/libcharon/daemon.c60
-rw-r--r--src/libcharon/daemon.h12
-rw-r--r--src/libcharon/encoding/message.c34
-rw-r--r--src/libcharon/encoding/payloads/cert_payload.c7
-rw-r--r--src/libcharon/kernel/kernel_interface.c36
-rw-r--r--src/libcharon/kernel/kernel_interface.h26
-rw-r--r--src/libcharon/kernel/kernel_ipsec.h26
-rw-r--r--src/libcharon/network/receiver.c51
-rw-r--r--src/libcharon/network/sender.c41
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.am18
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in (renamed from src/libcharon/plugins/resolve/Makefile.in)59
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_narrow.c154
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_narrow.h49
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_plugin.c72
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_plugin.h (renamed from src/libcharon/plugins/resolve/resolve_plugin.h)24
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_validator.c124
-rw-r--r--src/libcharon/plugins/addrblock/addrblock_validator.h49
-rw-r--r--src/libcharon/plugins/android/Makefile.am5
-rw-r--r--src/libcharon/plugins/android/Makefile.in13
-rw-r--r--src/libcharon/plugins/android/android_creds.c294
-rw-r--r--src/libcharon/plugins/android/android_creds.h73
-rw-r--r--src/libcharon/plugins/android/android_handler.c4
-rw-r--r--src/libcharon/plugins/android/android_logger.c96
-rw-r--r--src/libcharon/plugins/android/android_logger.h (renamed from src/libcharon/plugins/resolve/resolve_handler.h)35
-rw-r--r--src/libcharon/plugins/android/android_plugin.c41
-rw-r--r--src/libcharon/plugins/android/android_service.c385
-rw-r--r--src/libcharon/plugins/android/android_service.h54
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in2
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c3
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka/eap_aka_peer.c1
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c3
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_gtc/eap_gtc.c4
-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_md5/eap_md5.c3
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c8
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.am2
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in9
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c131
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.c150
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.h8
-rw-r--r--src/libcharon/plugins/eap_radius/radius_client.c464
-rw-r--r--src/libcharon/plugins/eap_radius/radius_client.h34
-rw-r--r--src/libcharon/plugins/eap_radius/radius_message.c123
-rw-r--r--src/libcharon/plugins/eap_radius/radius_server.c212
-rw-r--r--src/libcharon/plugins/eap_radius/radius_server.h88
-rw-r--r--src/libcharon/plugins/eap_radius/radius_socket.c309
-rw-r--r--src/libcharon/plugins/eap_radius/radius_socket.h74
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in2
-rw-r--r--src/libcharon/plugins/eap_sim/eap_sim_peer.c1
-rw-r--r--src/libcharon/plugins/eap_sim_file/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.am18
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in592
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c177
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h54
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c100
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h42
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c180
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h54
-rw-r--r--src/libcharon/plugins/farp/Makefile.in2
-rw-r--r--src/libcharon/plugins/farp/farp_spoofer.c4
-rw-r--r--src/libcharon/plugins/ha/Makefile.am4
-rw-r--r--src/libcharon/plugins/ha/Makefile.in11
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c364
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.h60
-rw-r--r--src/libcharon/plugins/ha/ha_cache.c362
-rw-r--r--src/libcharon/plugins/ha/ha_cache.h78
-rw-r--r--src/libcharon/plugins/ha/ha_child.c84
-rw-r--r--src/libcharon/plugins/ha/ha_child.h12
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c26
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.h6
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c209
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.h11
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c101
-rw-r--r--src/libcharon/plugins/ha/ha_ike.h11
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c96
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.h28
-rw-r--r--src/libcharon/plugins/ha/ha_message.c102
-rw-r--r--src/libcharon/plugins/ha/ha_message.h26
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c45
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.h2
-rw-r--r--src/libcharon/plugins/ha/ha_segments.c220
-rw-r--r--src/libcharon/plugins/ha/ha_segments.h23
-rw-r--r--src/libcharon/plugins/ha/ha_socket.c58
-rw-r--r--src/libcharon/plugins/ha/ha_socket.h4
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c78
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.h2
-rw-r--r--src/libcharon/plugins/kernel_klips/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c27
-rw-r--r--src/libcharon/plugins/kernel_netlink/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c323
-rw-r--r--src/libcharon/plugins/kernel_pfkey/Makefile.in2
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c125
-rw-r--r--src/libcharon/plugins/kernel_pfroute/Makefile.in2
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c5
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_ipsec.c154
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c4
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c8
-rw-r--r--src/libcharon/plugins/medcli/medcli_plugin.c4
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in2
-rw-r--r--src/libcharon/plugins/medsrv/medsrv_plugin.c4
-rw-r--r--src/libcharon/plugins/nm/Makefile.in2
-rw-r--r--src/libcharon/plugins/nm/nm_plugin.c4
-rw-r--r--src/libcharon/plugins/nm/nm_service.c3
-rw-r--r--src/libcharon/plugins/resolve/Makefile.am18
-rw-r--r--src/libcharon/plugins/resolve/resolve_handler.c251
-rw-r--r--src/libcharon/plugins/resolve/resolve_plugin.c62
-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_raw/Makefile.in2
-rw-r--r--src/libcharon/plugins/socket_raw/socket_raw_socket.c14
-rw-r--r--src/libcharon/plugins/sql/Makefile.in2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c2
-rw-r--r--src/libcharon/plugins/sql/sql_plugin.c4
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in2
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c23
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c22
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c5
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c10
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c59
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c11
-rw-r--r--src/libcharon/plugins/uci/Makefile.in2
-rw-r--r--src/libcharon/plugins/uci/uci_config.c3
-rw-r--r--src/libcharon/plugins/uci/uci_plugin.c4
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.am3
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in15
-rw-r--r--src/libcharon/plugins/unit_tester/tests.h1
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_auth_info.c2
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_hashtable.c111
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_med_db.c6
-rw-r--r--src/libcharon/plugins/updown/Makefile.in2
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c71
-rw-r--r--src/libcharon/sa/authenticators/authenticator.c7
-rw-r--r--src/libcharon/sa/authenticators/authenticator.h24
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.c38
-rw-r--r--src/libcharon/sa/authenticators/eap/eap_method.h30
-rw-r--r--src/libcharon/sa/authenticators/eap_authenticator.c30
-rw-r--r--src/libcharon/sa/authenticators/psk_authenticator.c7
-rw-r--r--src/libcharon/sa/authenticators/pubkey_authenticator.c7
-rw-r--r--src/libcharon/sa/child_sa.c138
-rw-r--r--src/libcharon/sa/child_sa.h28
-rw-r--r--src/libcharon/sa/ike_sa.c726
-rw-r--r--src/libcharon/sa/ike_sa.h12
-rw-r--r--src/libcharon/sa/ike_sa_manager.c34
-rw-r--r--src/libcharon/sa/task_manager.c139
-rw-r--r--src/libcharon/sa/task_manager.h21
-rw-r--r--src/libcharon/sa/tasks/child_create.c111
-rw-r--r--src/libcharon/sa/tasks/child_delete.c4
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c95
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c12
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.c10
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c14
-rw-r--r--src/libcharon/sa/tasks/ike_config.c4
-rw-r--r--src/libcharon/sa/tasks/ike_init.c1
-rw-r--r--src/libcharon/sa/trap_manager.c2
188 files changed, 7443 insertions, 6787 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index d473b455e..3297654e9 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -12,7 +12,6 @@ config/child_cfg.c config/child_cfg.h \
config/ike_cfg.c config/ike_cfg.h \
config/peer_cfg.c config/peer_cfg.h \
config/proposal.c config/proposal.h \
-config/auth_cfg.c config/auth_cfg.h \
control/controller.c control/controller.h \
daemon.c daemon.h \
encoding/generator.c encoding/generator.h \
@@ -95,17 +94,13 @@ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
-sa/tasks/task.c sa/tasks/task.h \
-credentials/credential_manager.c credentials/credential_manager.h \
-credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
-credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
-credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
-credentials/credential_set.h
+sa/tasks/task.c sa/tasks/task.h
# adding the plugin source files
LOCAL_SRC_FILES += $(call add_plugin, android)
-ifneq ($(call plugin_enabled, android)),)
+ifneq ($(call plugin_enabled, android),)
+LOCAL_C_INCLUDES += frameworks/base/cmds/keystore
LOCAL_SHARED_LIBRARIES += libcutils
endif
@@ -114,7 +109,7 @@ LOCAL_SRC_FILES += $(call add_plugin, attr)
LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2)
-ifneq ($(call plugin_enabled, eap-aka-3gpp2)),)
+ifneq ($(call plugin_enabled, eap-aka-3gpp2),)
LOCAL_C_INCLUDES += $(libgmp_PATH)
LOCAL_SHARED_LIBRARIES += libgmp
endif
@@ -129,6 +124,8 @@ LOCAL_SRC_FILES += $(call add_plugin, eap-mschapv2)
LOCAL_SRC_FILES += $(call add_plugin, eap-sim)
+LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-sql)
+
LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-pseudonym)
LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-reauth)
@@ -146,6 +143,8 @@ endif
LOCAL_SRC_FILES += $(call add_plugin, kernel-netlink)
+LOCAL_SRC_FILES += $(call add_plugin, kernel-pfkey)
+
LOCAL_SRC_FILES += $(call add_plugin, load-tester)
LOCAL_SRC_FILES += $(call add_plugin, socket-default)
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index 0eaccf7a0..44501c0d0 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -10,7 +10,6 @@ config/child_cfg.c config/child_cfg.h \
config/ike_cfg.c config/ike_cfg.h \
config/peer_cfg.c config/peer_cfg.h \
config/proposal.c config/proposal.h \
-config/auth_cfg.c config/auth_cfg.h \
control/controller.c control/controller.h \
daemon.c daemon.h \
encoding/generator.c encoding/generator.h \
@@ -93,12 +92,7 @@ sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
sa/tasks/ike_vendor.c sa/tasks/ike_vendor.h \
-sa/tasks/task.c sa/tasks/task.h \
-credentials/credential_manager.c credentials/credential_manager.h \
-credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
-credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
-credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
-credentials/credential_set.h
+sa/tasks/task.c sa/tasks/task.h
daemon.lo : $(top_builddir)/config.status
@@ -128,7 +122,7 @@ if USE_ME
sa/tasks/ike_me.c sa/tasks/ike_me.h
endif
-if USE_CAPABILITIES
+if USE_LIBCAP
libcharon_la_LIBADD += -lcap
endif
@@ -271,6 +265,14 @@ if MONOLITHIC
endif
endif
+if USE_EAP_SIMAKA_SQL
+ SUBDIRS += plugins/eap_simaka_sql
+ PLUGINS += eap-simaka-sql
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+endif
+endif
+
if USE_EAP_SIMAKA_PSEUDONYM
SUBDIRS += plugins/eap_simaka_pseudonym
PLUGINS += eap-simaka-pseudonym
@@ -374,14 +376,6 @@ if MONOLITHIC
endif
endif
-if USE_RESOLVE
- SUBDIRS += plugins/resolve
- PLUGINS += resolve
-if MONOLITHIC
- libcharon_la_LIBADD += plugins/resolve/libstrongswan-resolve.la
-endif
-endif
-
if USE_ANDROID
SUBDIRS += plugins/android
PLUGINS += android
@@ -406,6 +400,14 @@ if MONOLITHIC
endif
endif
+if USE_ADDRBLOCK
+ SUBDIRS += plugins/addrblock
+ PLUGINS += addrblock
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/uci/libstrongswan-addrblock.la
+endif
+endif
+
if USE_UNIT_TESTS
SUBDIRS += plugins/unit_tester
PLUGINS += unit-tester
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index 0eb6f36f4..8e58b0e2e 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -44,7 +44,7 @@ host_triplet = @host@
@USE_ME_TRUE@ sa/mediation_manager.c sa/mediation_manager.h \
@USE_ME_TRUE@ sa/tasks/ike_me.c sa/tasks/ike_me.h
-@USE_CAPABILITIES_TRUE@am__append_2 = -lcap
+@USE_LIBCAP_TRUE@am__append_2 = -lcap
@USE_LOAD_TESTER_TRUE@am__append_3 = plugins/load_tester
@USE_LOAD_TESTER_TRUE@am__append_4 = load-tester
@MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE@am__append_5 = plugins/load_tester/libstrongswan-load-tester.la
@@ -93,46 +93,46 @@ host_triplet = @host@
@USE_EAP_SIM_FILE_TRUE@am__append_48 = plugins/eap_sim_file
@USE_EAP_SIM_FILE_TRUE@am__append_49 = eap-sim-file
@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_50 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_51 = plugins/eap_simaka_pseudonym
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_52 = eap-simaka-pseudonym
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_53 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_54 = plugins/eap_simaka_reauth
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_55 = eap-simaka-reauth
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_56 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
-@USE_EAP_AKA_TRUE@am__append_57 = plugins/eap_aka
-@USE_EAP_AKA_TRUE@am__append_58 = eap-aka
-@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_59 = plugins/eap_aka/libstrongswan-eap-aka.la
-@USE_EAP_AKA_3GPP2_TRUE@am__append_60 = plugins/eap_aka_3gpp2
-@USE_EAP_AKA_3GPP2_TRUE@am__append_61 = eap-aka-3gpp2
-@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_62 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
-@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_63 = $(top_builddir)/src/libsimaka/libsimaka.la
-@USE_EAP_MD5_TRUE@am__append_64 = plugins/eap_md5
-@USE_EAP_MD5_TRUE@am__append_65 = eap-md5
-@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_66 = plugins/eap_md5/libstrongswan-eap-md5.la
-@USE_EAP_GTC_TRUE@am__append_67 = plugins/eap_gtc
-@USE_EAP_GTC_TRUE@am__append_68 = eap-gtc
-@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_69 = plugins/eap_gtc/libstrongswan-eap-gtc.la
-@USE_EAP_MSCHAPV2_TRUE@am__append_70 = plugins/eap_mschapv2
-@USE_EAP_MSCHAPV2_TRUE@am__append_71 = eap-mschapv2
-@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_72 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
-@USE_EAP_RADIUS_TRUE@am__append_73 = plugins/eap_radius
-@USE_EAP_RADIUS_TRUE@am__append_74 = eap-radius
-@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_75 = plugins/eap_radius/libstrongswan-eap-radius.la
-@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv
-@USE_MEDSRV_TRUE@am__append_77 = medsrv
-@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_78 = plugins/medsrv/libstrongswan-medsrv.la
-@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli
-@USE_MEDCLI_TRUE@am__append_80 = medcli
-@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_81 = plugins/medcli/libstrongswan-medcli.la
-@USE_NM_TRUE@am__append_82 = plugins/nm
-@USE_NM_TRUE@am__append_83 = nm
-@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_84 = plugins/nm/libstrongswan-nm.la
-@USE_DHCP_TRUE@am__append_85 = plugins/dhcp
-@USE_DHCP_TRUE@am__append_86 = dhcp
-@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_87 = plugins/dhcp/libstrongswan-dhcp.la
-@USE_RESOLVE_TRUE@am__append_88 = plugins/resolve
-@USE_RESOLVE_TRUE@am__append_89 = resolve
-@MONOLITHIC_TRUE@@USE_RESOLVE_TRUE@am__append_90 = plugins/resolve/libstrongswan-resolve.la
+@USE_EAP_SIMAKA_SQL_TRUE@am__append_51 = plugins/eap_simaka_sql
+@USE_EAP_SIMAKA_SQL_TRUE@am__append_52 = eap-simaka-sql
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_53 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_54 = plugins/eap_simaka_pseudonym
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_55 = eap-simaka-pseudonym
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_56 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_57 = plugins/eap_simaka_reauth
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_58 = eap-simaka-reauth
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_59 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+@USE_EAP_AKA_TRUE@am__append_60 = plugins/eap_aka
+@USE_EAP_AKA_TRUE@am__append_61 = eap-aka
+@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_62 = plugins/eap_aka/libstrongswan-eap-aka.la
+@USE_EAP_AKA_3GPP2_TRUE@am__append_63 = plugins/eap_aka_3gpp2
+@USE_EAP_AKA_3GPP2_TRUE@am__append_64 = eap-aka-3gpp2
+@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_65 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_66 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_EAP_MD5_TRUE@am__append_67 = plugins/eap_md5
+@USE_EAP_MD5_TRUE@am__append_68 = eap-md5
+@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_69 = plugins/eap_md5/libstrongswan-eap-md5.la
+@USE_EAP_GTC_TRUE@am__append_70 = plugins/eap_gtc
+@USE_EAP_GTC_TRUE@am__append_71 = eap-gtc
+@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_72 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+@USE_EAP_MSCHAPV2_TRUE@am__append_73 = plugins/eap_mschapv2
+@USE_EAP_MSCHAPV2_TRUE@am__append_74 = eap-mschapv2
+@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_75 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+@USE_EAP_RADIUS_TRUE@am__append_76 = plugins/eap_radius
+@USE_EAP_RADIUS_TRUE@am__append_77 = eap-radius
+@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_78 = plugins/eap_radius/libstrongswan-eap-radius.la
+@USE_MEDSRV_TRUE@am__append_79 = plugins/medsrv
+@USE_MEDSRV_TRUE@am__append_80 = medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_81 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_82 = plugins/medcli
+@USE_MEDCLI_TRUE@am__append_83 = medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_84 = plugins/medcli/libstrongswan-medcli.la
+@USE_NM_TRUE@am__append_85 = plugins/nm
+@USE_NM_TRUE@am__append_86 = nm
+@MONOLITHIC_TRUE@@USE_NM_TRUE@am__append_87 = plugins/nm/libstrongswan-nm.la
+@USE_DHCP_TRUE@am__append_88 = plugins/dhcp
+@USE_DHCP_TRUE@am__append_89 = dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_90 = plugins/dhcp/libstrongswan-dhcp.la
@USE_ANDROID_TRUE@am__append_91 = plugins/android
@USE_ANDROID_TRUE@am__append_92 = android
@MONOLITHIC_TRUE@@USE_ANDROID_TRUE@am__append_93 = plugins/android/libstrongswan-android.la
@@ -142,9 +142,12 @@ host_triplet = @host@
@USE_UCI_TRUE@am__append_97 = plugins/uci
@USE_UCI_TRUE@am__append_98 = uci
@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_99 = plugins/uci/libstrongswan-uci.la
-@USE_UNIT_TESTS_TRUE@am__append_100 = plugins/unit_tester
-@USE_UNIT_TESTS_TRUE@am__append_101 = unit-tester
-@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_102 = plugins/unit_tester/libstrongswan-unit-tester.la
+@USE_ADDRBLOCK_TRUE@am__append_100 = plugins/addrblock
+@USE_ADDRBLOCK_TRUE@am__append_101 = addrblock
+@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_102 = plugins/uci/libstrongswan-addrblock.la
+@USE_UNIT_TESTS_TRUE@am__append_103 = plugins/unit_tester
+@USE_UNIT_TESTS_TRUE@am__append_104 = unit-tester
+@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_105 = plugins/unit_tester/libstrongswan-unit-tester.la
subdir = src/libcharon
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -194,11 +197,11 @@ libcharon_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__append_38) $(am__append_41) $(am__append_44) \
$(am__append_47) $(am__append_50) $(am__append_53) \
$(am__append_56) $(am__append_59) $(am__append_62) \
- $(am__append_63) $(am__append_66) $(am__append_69) \
+ $(am__append_65) $(am__append_66) $(am__append_69) \
$(am__append_72) $(am__append_75) $(am__append_78) \
$(am__append_81) $(am__append_84) $(am__append_87) \
$(am__append_90) $(am__append_93) $(am__append_96) \
- $(am__append_99) $(am__append_102)
+ $(am__append_99) $(am__append_102) $(am__append_105)
am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
bus/listeners/listener.h bus/listeners/file_logger.c \
bus/listeners/file_logger.h bus/listeners/sys_logger.c \
@@ -206,11 +209,10 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
config/backend_manager.h config/backend.h config/child_cfg.c \
config/child_cfg.h config/ike_cfg.c config/ike_cfg.h \
config/peer_cfg.c config/peer_cfg.h config/proposal.c \
- config/proposal.h config/auth_cfg.c config/auth_cfg.h \
- control/controller.c control/controller.h daemon.c daemon.h \
- encoding/generator.c encoding/generator.h encoding/message.c \
- encoding/message.h encoding/parser.c encoding/parser.h \
- encoding/payloads/auth_payload.c \
+ config/proposal.h control/controller.c control/controller.h \
+ daemon.c daemon.h encoding/generator.c encoding/generator.h \
+ encoding/message.c encoding/message.h encoding/parser.c \
+ encoding/parser.h encoding/payloads/auth_payload.c \
encoding/payloads/auth_payload.h \
encoding/payloads/cert_payload.c \
encoding/payloads/cert_payload.h \
@@ -311,14 +313,6 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- credentials/credential_manager.c \
- credentials/credential_manager.h \
- credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
- credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/credential_set.h \
encoding/payloads/endpoint_notify.c \
encoding/payloads/endpoint_notify.h \
processing/jobs/initiate_mediation_job.c \
@@ -332,32 +326,31 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
@USE_ME_TRUE@ connect_manager.lo mediation_manager.lo ike_me.lo
am_libcharon_la_OBJECTS = bus.lo file_logger.lo sys_logger.lo \
backend_manager.lo child_cfg.lo ike_cfg.lo peer_cfg.lo \
- proposal.lo auth_cfg.lo controller.lo daemon.lo generator.lo \
- message.lo parser.lo auth_payload.lo cert_payload.lo \
- certreq_payload.lo configuration_attribute.lo cp_payload.lo \
- delete_payload.lo eap_payload.lo encodings.lo \
- encryption_payload.lo id_payload.lo ike_header.lo \
- ke_payload.lo nonce_payload.lo notify_payload.lo payload.lo \
- proposal_substructure.lo sa_payload.lo \
- traffic_selector_substructure.lo transform_attribute.lo \
- transform_substructure.lo ts_payload.lo unknown_payload.lo \
- vendor_id_payload.lo kernel_interface.lo kernel_ipsec.lo \
- packet.lo receiver.lo sender.lo socket_manager.lo \
- acquire_job.lo callback_job.lo delete_child_sa_job.lo \
- delete_ike_sa_job.lo migrate_job.lo process_message_job.lo \
- rekey_child_sa_job.lo rekey_ike_sa_job.lo retransmit_job.lo \
- send_dpd_job.lo send_keepalive_job.lo roam_job.lo \
- update_sa_job.lo inactivity_job.lo scheduler.lo processor.lo \
- authenticator.lo eap_authenticator.lo eap_method.lo \
- eap_manager.lo sim_manager.lo psk_authenticator.lo \
- pubkey_authenticator.lo child_sa.lo ike_sa.lo ike_sa_id.lo \
- ike_sa_manager.lo task_manager.lo keymat.lo trap_manager.lo \
- child_create.lo child_delete.lo child_rekey.lo ike_auth.lo \
- ike_cert_pre.lo ike_cert_post.lo ike_config.lo ike_delete.lo \
- ike_dpd.lo ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \
+ proposal.lo controller.lo daemon.lo generator.lo message.lo \
+ parser.lo auth_payload.lo cert_payload.lo certreq_payload.lo \
+ configuration_attribute.lo cp_payload.lo delete_payload.lo \
+ eap_payload.lo encodings.lo encryption_payload.lo \
+ id_payload.lo ike_header.lo ke_payload.lo nonce_payload.lo \
+ notify_payload.lo payload.lo proposal_substructure.lo \
+ sa_payload.lo traffic_selector_substructure.lo \
+ transform_attribute.lo transform_substructure.lo ts_payload.lo \
+ unknown_payload.lo vendor_id_payload.lo kernel_interface.lo \
+ kernel_ipsec.lo packet.lo receiver.lo sender.lo \
+ socket_manager.lo acquire_job.lo callback_job.lo \
+ delete_child_sa_job.lo delete_ike_sa_job.lo migrate_job.lo \
+ process_message_job.lo rekey_child_sa_job.lo \
+ rekey_ike_sa_job.lo retransmit_job.lo send_dpd_job.lo \
+ send_keepalive_job.lo roam_job.lo update_sa_job.lo \
+ inactivity_job.lo scheduler.lo processor.lo authenticator.lo \
+ eap_authenticator.lo eap_method.lo eap_manager.lo \
+ sim_manager.lo psk_authenticator.lo pubkey_authenticator.lo \
+ child_sa.lo ike_sa.lo ike_sa_id.lo ike_sa_manager.lo \
+ task_manager.lo keymat.lo trap_manager.lo child_create.lo \
+ child_delete.lo child_rekey.lo ike_auth.lo ike_cert_pre.lo \
+ ike_cert_post.lo ike_config.lo ike_delete.lo ike_dpd.lo \
+ ike_init.lo ike_natd.lo ike_mobike.lo ike_rekey.lo \
ike_reauth.lo ike_auth_lifetime.lo ike_vendor.lo task.lo \
- credential_manager.lo auth_cfg_wrapper.lo \
- ocsp_response_wrapper.lo cert_cache.lo $(am__objects_1)
+ $(am__objects_1)
libcharon_la_OBJECTS = $(am_libcharon_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -394,12 +387,12 @@ DIST_SUBDIRS = . plugins/load_tester plugins/kernel_pfkey \
plugins/socket_raw plugins/socket_dynamic plugins/farp \
plugins/stroke plugins/smp plugins/sql plugins/updown \
plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \
- plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
- plugins/eap_aka plugins/eap_aka_3gpp2 plugins/eap_md5 \
- plugins/eap_gtc plugins/eap_mschapv2 plugins/eap_radius \
- plugins/medsrv plugins/medcli plugins/nm plugins/dhcp \
- plugins/resolve plugins/android plugins/ha plugins/uci \
- plugins/unit_tester
+ plugins/eap_simaka_sql plugins/eap_simaka_pseudonym \
+ plugins/eap_simaka_reauth plugins/eap_aka \
+ plugins/eap_aka_3gpp2 plugins/eap_md5 plugins/eap_gtc \
+ plugins/eap_mschapv2 plugins/eap_radius plugins/medsrv \
+ plugins/medcli plugins/nm plugins/dhcp plugins/android \
+ plugins/ha plugins/uci plugins/addrblock plugins/unit_tester
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -589,10 +582,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
config/backend.h config/child_cfg.c config/child_cfg.h \
config/ike_cfg.c config/ike_cfg.h config/peer_cfg.c \
config/peer_cfg.h config/proposal.c config/proposal.h \
- config/auth_cfg.c config/auth_cfg.h control/controller.c \
- control/controller.h daemon.c daemon.h encoding/generator.c \
- encoding/generator.h encoding/message.c encoding/message.h \
- encoding/parser.c encoding/parser.h \
+ control/controller.c control/controller.h daemon.c daemon.h \
+ encoding/generator.c encoding/generator.h encoding/message.c \
+ encoding/message.h encoding/parser.c encoding/parser.h \
encoding/payloads/auth_payload.c \
encoding/payloads/auth_payload.h \
encoding/payloads/cert_payload.c \
@@ -694,14 +686,7 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
sa/tasks/ike_reauth.h sa/tasks/ike_auth_lifetime.c \
sa/tasks/ike_auth_lifetime.h sa/tasks/ike_vendor.c \
sa/tasks/ike_vendor.h sa/tasks/task.c sa/tasks/task.h \
- credentials/credential_manager.c \
- credentials/credential_manager.h \
- credentials/sets/auth_cfg_wrapper.c \
- credentials/sets/auth_cfg_wrapper.h \
- credentials/sets/ocsp_response_wrapper.c \
- credentials/sets/ocsp_response_wrapper.h \
- credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
- credentials/credential_set.h $(am__append_1)
+ $(am__append_1)
INCLUDES = \
-I${linux_headers} \
-I$(top_srcdir)/src/libstrongswan \
@@ -718,11 +703,11 @@ libcharon_la_LIBADD = -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB) \
$(am__append_38) $(am__append_41) $(am__append_44) \
$(am__append_47) $(am__append_50) $(am__append_53) \
$(am__append_56) $(am__append_59) $(am__append_62) \
- $(am__append_63) $(am__append_66) $(am__append_69) \
+ $(am__append_65) $(am__append_66) $(am__append_69) \
$(am__append_72) $(am__append_75) $(am__append_78) \
$(am__append_81) $(am__append_84) $(am__append_87) \
$(am__append_90) $(am__append_93) $(am__append_96) \
- $(am__append_99) $(am__append_102)
+ $(am__append_99) $(am__append_102) $(am__append_105)
EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_3) $(am__append_6) \
@MONOLITHIC_FALSE@ $(am__append_9) $(am__append_12) \
@@ -734,13 +719,13 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_45) $(am__append_48) \
@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_54) \
@MONOLITHIC_FALSE@ $(am__append_57) $(am__append_60) \
-@MONOLITHIC_FALSE@ $(am__append_64) $(am__append_67) \
+@MONOLITHIC_FALSE@ $(am__append_63) $(am__append_67) \
@MONOLITHIC_FALSE@ $(am__append_70) $(am__append_73) \
@MONOLITHIC_FALSE@ $(am__append_76) $(am__append_79) \
@MONOLITHIC_FALSE@ $(am__append_82) $(am__append_85) \
@MONOLITHIC_FALSE@ $(am__append_88) $(am__append_91) \
@MONOLITHIC_FALSE@ $(am__append_94) $(am__append_97) \
-@MONOLITHIC_FALSE@ $(am__append_100)
+@MONOLITHIC_FALSE@ $(am__append_100) $(am__append_103)
# build optional plugins
########################
@@ -754,13 +739,13 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_45) $(am__append_48) \
@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_54) \
@MONOLITHIC_TRUE@ $(am__append_57) $(am__append_60) \
-@MONOLITHIC_TRUE@ $(am__append_64) $(am__append_67) \
+@MONOLITHIC_TRUE@ $(am__append_63) $(am__append_67) \
@MONOLITHIC_TRUE@ $(am__append_70) $(am__append_73) \
@MONOLITHIC_TRUE@ $(am__append_76) $(am__append_79) \
@MONOLITHIC_TRUE@ $(am__append_82) $(am__append_85) \
@MONOLITHIC_TRUE@ $(am__append_88) $(am__append_91) \
@MONOLITHIC_TRUE@ $(am__append_94) $(am__append_97) \
-@MONOLITHIC_TRUE@ $(am__append_100)
+@MONOLITHIC_TRUE@ $(am__append_100) $(am__append_103)
PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins} $(am__append_4) \
$(am__append_7) $(am__append_10) $(am__append_13) \
$(am__append_16) $(am__append_19) $(am__append_22) \
@@ -768,11 +753,11 @@ PLUGINS = ${libstrongswan_plugins} ${libhydra_plugins} $(am__append_4) \
$(am__append_34) $(am__append_37) $(am__append_40) \
$(am__append_43) $(am__append_46) $(am__append_49) \
$(am__append_52) $(am__append_55) $(am__append_58) \
- $(am__append_61) $(am__append_65) $(am__append_68) \
+ $(am__append_61) $(am__append_64) $(am__append_68) \
$(am__append_71) $(am__append_74) $(am__append_77) \
$(am__append_80) $(am__append_83) $(am__append_86) \
$(am__append_89) $(am__append_92) $(am__append_95) \
- $(am__append_98) $(am__append_101)
+ $(am__append_98) $(am__append_101) $(am__append_104)
all: all-recursive
.SUFFIXES:
@@ -848,14 +833,11 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acquire_job.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg_wrapper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authenticator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bus.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback_job.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certreq_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/child_cfg.Plo@am__quote@
@@ -867,7 +849,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp_payload.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_child_sa_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delete_ike_sa_job.Plo@am__quote@
@@ -913,7 +894,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/migrate_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nonce_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_payload.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/payload.Plo@am__quote@
@@ -1025,13 +1005,6 @@ proposal.lo: config/proposal.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o proposal.lo `test -f 'config/proposal.c' || echo '$(srcdir)/'`config/proposal.c
-auth_cfg.lo: config/auth_cfg.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.lo -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/auth_cfg.c' object='auth_cfg.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg.lo `test -f 'config/auth_cfg.c' || echo '$(srcdir)/'`config/auth_cfg.c
-
controller.lo: control/controller.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT controller.lo -MD -MP -MF $(DEPDIR)/controller.Tpo -c -o controller.lo `test -f 'control/controller.c' || echo '$(srcdir)/'`control/controller.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/controller.Tpo $(DEPDIR)/controller.Plo
@@ -1592,34 +1565,6 @@ task.lo: sa/tasks/task.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.lo `test -f 'sa/tasks/task.c' || echo '$(srcdir)/'`sa/tasks/task.c
-credential_manager.lo: credentials/credential_manager.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.lo -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
-
-auth_cfg_wrapper.lo: credentials/sets/auth_cfg_wrapper.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.lo -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
-
-ocsp_response_wrapper.lo: credentials/sets/ocsp_response_wrapper.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.lo -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
-
-cert_cache.lo: credentials/sets/cert_cache.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.lo -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
-
endpoint_notify.lo: encoding/payloads/endpoint_notify.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT endpoint_notify.lo -MD -MP -MF $(DEPDIR)/endpoint_notify.Tpo -c -o endpoint_notify.lo `test -f 'encoding/payloads/endpoint_notify.c' || echo '$(srcdir)/'`encoding/payloads/endpoint_notify.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/endpoint_notify.Tpo $(DEPDIR)/endpoint_notify.Plo
@@ -1675,7 +1620,7 @@ clean-libtool:
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
@@ -1700,7 +1645,7 @@ $(RECURSIVE_TARGETS):
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index 764744a41..441009e5e 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -102,20 +102,16 @@ static void entry_destroy(entry_t *entry)
free(entry);
}
-/**
- * Implementation of bus_t.add_listener.
- */
-static void add_listener(private_bus_t *this, listener_t *listener)
+METHOD(bus_t, add_listener, void,
+ private_bus_t *this, listener_t *listener)
{
this->mutex->lock(this->mutex);
this->listeners->insert_last(this->listeners, entry_create(listener, FALSE));
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.remove_listener.
- */
-static void remove_listener(private_bus_t *this, listener_t *listener)
+METHOD(bus_t, remove_listener, void,
+ private_bus_t *this, listener_t *listener)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -156,10 +152,8 @@ static void listener_cleanup(cleanup_data_t *data)
entry_destroy(data->entry);
}
-/**
- * Implementation of bus_t.listen.
- */
-static void listen_(private_bus_t *this, listener_t *listener, job_t *job)
+METHOD(bus_t, listen_, void,
+ private_bus_t *this, listener_t *listener, job_t *job)
{
bool old;
cleanup_data_t data;
@@ -184,18 +178,14 @@ static void listen_(private_bus_t *this, listener_t *listener, job_t *job)
entry_destroy(data.entry);
}
-/**
- * Implementation of bus_t.set_sa.
- */
-static void set_sa(private_bus_t *this, ike_sa_t *ike_sa)
+METHOD(bus_t, set_sa, void,
+ private_bus_t *this, ike_sa_t *ike_sa)
{
this->thread_sa->set(this->thread_sa, ike_sa);
}
-/**
- * Implementation of bus_t.get_sa
- */
-static ike_sa_t* get_sa(private_bus_t *this)
+METHOD(bus_t, get_sa, ike_sa_t*,
+ private_bus_t *this)
{
return this->thread_sa->get(this->thread_sa);
}
@@ -252,11 +242,9 @@ static bool log_cb(entry_t *entry, log_data_t *data)
return FALSE;
}
-/**
- * Implementation of bus_t.vlog.
- */
-static void vlog(private_bus_t *this, debug_t group, level_t level,
- char* format, va_list args)
+METHOD(bus_t, vlog, void,
+ private_bus_t *this, debug_t group, level_t level,
+ char* format, va_list args)
{
log_data_t data;
@@ -276,11 +264,8 @@ static void vlog(private_bus_t *this, debug_t group, level_t level,
va_end(data.args);
}
-/**
- * Implementation of bus_t.log.
- */
-static void log_(private_bus_t *this, debug_t group, level_t level,
- char* format, ...)
+METHOD(bus_t, log_, void,
+ private_bus_t *this, debug_t group, level_t level, char* format, ...)
{
va_list args;
@@ -307,10 +292,8 @@ static void unregister_listener(private_bus_t *this, entry_t *entry,
this->listeners->remove_at(this->listeners, enumerator);
}
-/**
- * Implementation of bus_t.alert
- */
-static void alert(private_bus_t *this, alert_t alert, ...)
+METHOD(bus_t, alert, void,
+ private_bus_t *this, alert_t alert, ...)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -342,11 +325,8 @@ static void alert(private_bus_t *this, alert_t alert, ...)
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.ike_state_change
- */
-static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa,
- ike_sa_state_t state)
+METHOD(bus_t, ike_state_change, void,
+ private_bus_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -372,11 +352,8 @@ static void ike_state_change(private_bus_t *this, ike_sa_t *ike_sa,
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.child_state_change
- */
-static void child_state_change(private_bus_t *this, child_sa_t *child_sa,
- child_sa_state_t state)
+METHOD(bus_t, child_state_change, void,
+ private_bus_t *this, child_sa_t *child_sa, child_sa_state_t state)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -406,10 +383,8 @@ static void child_state_change(private_bus_t *this, child_sa_t *child_sa,
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.message
- */
-static void message(private_bus_t *this, message_t *message, bool incoming)
+METHOD(bus_t, message, void,
+ private_bus_t *this, message_t *message, bool incoming)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -439,12 +414,9 @@ static void message(private_bus_t *this, message_t *message, bool incoming)
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.ike_keys
- */
-static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa,
- diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
- ike_sa_t *rekey)
+METHOD(bus_t, ike_keys, void,
+ private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -471,11 +443,9 @@ static void ike_keys(private_bus_t *this, ike_sa_t *ike_sa,
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.child_keys
- */
-static void child_keys(private_bus_t *this, child_sa_t *child_sa,
- diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
+METHOD(bus_t, child_keys, void,
+ private_bus_t *this, child_sa_t *child_sa, bool initiator,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -494,7 +464,7 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa,
}
entry->calling++;
keep = entry->listener->child_keys(entry->listener, ike_sa, child_sa,
- dh, nonce_i, nonce_r);
+ initiator, dh, nonce_i, nonce_r);
entry->calling--;
if (!keep)
{
@@ -505,10 +475,8 @@ static void child_keys(private_bus_t *this, child_sa_t *child_sa,
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.child_updown
- */
-static void child_updown(private_bus_t *this, child_sa_t *child_sa, bool up)
+METHOD(bus_t, child_updown, void,
+ private_bus_t *this, child_sa_t *child_sa, bool up)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -538,10 +506,8 @@ static void child_updown(private_bus_t *this, child_sa_t *child_sa, bool up)
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.child_rekey
- */
-static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new)
+METHOD(bus_t, child_rekey, void,
+ private_bus_t *this, child_sa_t *old, child_sa_t *new)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -570,10 +536,8 @@ static void child_rekey(private_bus_t *this, child_sa_t *old, child_sa_t *new)
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.ike_updown
- */
-static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up)
+METHOD(bus_t, ike_updown, void,
+ private_bus_t *this, ike_sa_t *ike_sa, bool up)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -613,10 +577,8 @@ static void ike_updown(private_bus_t *this, ike_sa_t *ike_sa, bool up)
}
}
-/**
- * Implementation of bus_t.ike_rekey
- */
-static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
+METHOD(bus_t, ike_rekey, void,
+ private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
{
enumerator_t *enumerator;
entry_t *entry;
@@ -642,10 +604,8 @@ static void ike_rekey(private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of bus_t.authorize
- */
-static bool authorize(private_bus_t *this, bool final)
+METHOD(bus_t, authorize, bool,
+ private_bus_t *this, bool final)
{
enumerator_t *enumerator;
ike_sa_t *ike_sa;
@@ -680,10 +640,40 @@ static bool authorize(private_bus_t *this, bool final)
return success;
}
-/**
- * Implementation of bus_t.destroy.
- */
-static void destroy(private_bus_t *this)
+METHOD(bus_t, narrow, void,
+ private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
+ linked_list_t *local, linked_list_t *remote)
+{
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ bool keep;
+
+ ike_sa = this->thread_sa->get(this->thread_sa);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->narrow)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
+ type, local, remote);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(bus_t, destroy, void,
+ private_bus_t *this)
{
this->thread_sa->destroy(this->thread_sa);
this->mutex->destroy(this->mutex);
@@ -696,31 +686,35 @@ static void destroy(private_bus_t *this)
*/
bus_t *bus_create()
{
- private_bus_t *this = malloc_thing(private_bus_t);
-
- this->public.add_listener = (void(*)(bus_t*,listener_t*))add_listener;
- this->public.remove_listener = (void(*)(bus_t*,listener_t*))remove_listener;
- this->public.listen = (void(*)(bus_t*, listener_t *listener, job_t *job))listen_;
- this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa;
- this->public.get_sa = (ike_sa_t*(*)(bus_t*))get_sa;
- this->public.log = (void(*)(bus_t*,debug_t,level_t,char*,...))log_;
- this->public.vlog = (void(*)(bus_t*,debug_t,level_t,char*,va_list))vlog;
- this->public.alert = (void(*)(bus_t*, alert_t alert, ...))alert;
- this->public.ike_state_change = (void(*)(bus_t*,ike_sa_t*,ike_sa_state_t))ike_state_change;
- this->public.child_state_change = (void(*)(bus_t*,child_sa_t*,child_sa_state_t))child_state_change;
- this->public.message = (void(*)(bus_t*, message_t *message, bool incoming))message;
- this->public.ike_keys = (void(*)(bus_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
- this->public.child_keys = (void(*)(bus_t*, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
- this->public.ike_updown = (void(*)(bus_t*, ike_sa_t *ike_sa, bool up))ike_updown;
- this->public.ike_rekey = (void(*)(bus_t*, ike_sa_t *old, ike_sa_t *new))ike_rekey;
- this->public.child_updown = (void(*)(bus_t*, child_sa_t *child_sa, bool up))child_updown;
- this->public.child_rekey = (void(*)(bus_t*, child_sa_t *old, child_sa_t *new))child_rekey;
- this->public.authorize = (bool(*)(bus_t*, bool final))authorize;
- this->public.destroy = (void(*)(bus_t*)) destroy;
-
- this->listeners = linked_list_create();
- this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
- this->thread_sa = thread_value_create(NULL);
+ private_bus_t *this;
+
+ INIT(this,
+ .public = {
+ .add_listener = _add_listener,
+ .remove_listener = _remove_listener,
+ .listen = _listen_,
+ .set_sa = _set_sa,
+ .get_sa = _get_sa,
+ .log = _log_,
+ .vlog = _vlog,
+ .alert = _alert,
+ .ike_state_change = _ike_state_change,
+ .child_state_change = _child_state_change,
+ .message = _message,
+ .ike_keys = _ike_keys,
+ .child_keys = _child_keys,
+ .ike_updown = _ike_updown,
+ .ike_rekey = _ike_rekey,
+ .child_updown = _child_updown,
+ .child_rekey = _child_rekey,
+ .authorize = _authorize,
+ .narrow = _narrow,
+ .destroy = _destroy,
+ },
+ .listeners = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+ .thread_sa = thread_value_create(NULL),
+ );
return &this->public;
}
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
index 8cf392eae..6a306afcc 100644
--- a/src/libcharon/bus/bus.h
+++ b/src/libcharon/bus/bus.h
@@ -22,6 +22,7 @@
#define BUS_H_
typedef enum alert_t alert_t;
+typedef enum narrow_hook_t narrow_hook_t;
typedef struct bus_t bus_t;
#include <stdarg.h>
@@ -86,6 +87,31 @@ enum alert_t {
};
/**
+ * Kind of narrow hook.
+ *
+ * There is a non-authenticated (IKE_AUTH) and a authenticated
+ * (CREATE_CHILD_SA) narrowing hook for the initiator. Only one of these
+ * hooks is invoked before the exchange.
+ * To verify the traffic selectors negotiated, each PRE hook has a POST
+ * counterpart that follows. POST hooks are invoked with an authenticated peer.
+ * It is usually not a good idea to narrow in the POST hooks,
+ * as the resulting traffic selector is not negotiated and results
+ * in non-matching policies.
+ */
+enum narrow_hook_t {
+ /** invoked as initiator before exchange, peer is not yet authenticated */
+ NARROW_INITIATOR_PRE_NOAUTH,
+ /** invoked as initiator before exchange, peer is authenticated */
+ NARROW_INITIATOR_PRE_AUTH,
+ /** invoked as responder during exchange, peer is authenticated */
+ NARROW_RESPONDER,
+ /** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */
+ NARROW_INITIATOR_POST_NOAUTH,
+ /** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */
+ NARROW_INITIATOR_POST_AUTH,
+};
+
+/**
* The bus receives events and sends them to all registered listeners.
*
* Any events sent to are delivered to all registered listeners. Threads
@@ -217,6 +243,17 @@ struct bus_t {
bool (*authorize)(bus_t *this, bool final);
/**
+ * CHILD_SA traffic selector narrowing hook.
+ *
+ * @param child_sa CHILD_SA set up with these traffic selectors
+ * @param type type of hook getting invoked
+ * @param local list of local traffic selectors to narrow
+ * @param remote list of remote traffic selectors to narrow
+ */
+ void (*narrow)(bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
+ linked_list_t *local, linked_list_t *remote);
+
+ /**
* IKE_SA keymat hook.
*
* @param ike_sa IKE_SA this keymat belongs to
@@ -231,12 +268,13 @@ struct bus_t {
* CHILD_SA keymat hook.
*
* @param child_sa CHILD_SA this keymat is used for
+ * @param initiator initiator of the CREATE_CHILD_SA exchange
* @param dh diffie hellman shared secret
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
*/
- void (*child_keys)(bus_t *this, child_sa_t *child_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r);
+ void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
+ diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
/**
* IKE_SA up/down hook.
diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c
index 12587deaf..87db532f5 100644
--- a/src/libcharon/bus/listeners/file_logger.c
+++ b/src/libcharon/bus/listeners/file_logger.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include "file_logger.h"
@@ -40,6 +41,11 @@ struct private_file_logger_t {
* Maximum level to log, for each group
*/
level_t levels[DBG_MAX];
+
+ /**
+ * strftime() format of time prefix, if any
+ */
+ char *time_format;
};
/**
@@ -50,8 +56,17 @@ static bool log_(private_file_logger_t *this, debug_t group, level_t level,
{
if (level <= this->levels[group])
{
- char buffer[8192];
+ char buffer[8192], timestr[128];
char *current = buffer, *next;
+ struct tm tm;
+ time_t t;
+
+ if (this->time_format)
+ {
+ t = time(NULL);
+ localtime_r(&t, &tm);
+ strftime(timestr, sizeof(timestr), this->time_format, &tm);
+ }
/* write in memory buffer first */
vsnprintf(buffer, sizeof(buffer), format, args);
@@ -64,8 +79,16 @@ static bool log_(private_file_logger_t *this, debug_t group, level_t level,
{
*(next++) = '\0';
}
- fprintf(this->out, "%.2d[%N] %s\n",
- thread, debug_names, group, current);
+ if (this->time_format)
+ {
+ fprintf(this->out, "%s %.2d[%N] %s\n",
+ timestr, thread, debug_names, group, current);
+ }
+ else
+ {
+ fprintf(this->out, "%.2d[%N] %s\n",
+ thread, debug_names, group, current);
+ }
current = next;
}
}
@@ -106,7 +129,7 @@ static void destroy(private_file_logger_t *this)
/*
* Described in header.
*/
-file_logger_t *file_logger_create(FILE *out)
+file_logger_t *file_logger_create(FILE *out, char *time_format)
{
private_file_logger_t *this = malloc_thing(private_file_logger_t);
@@ -118,6 +141,7 @@ file_logger_t *file_logger_create(FILE *out)
/* private variables */
this->out = out;
+ this->time_format = time_format;
set_level(this, DBG_ANY, LEVEL_SILENT);
return &this->public;
diff --git a/src/libcharon/bus/listeners/file_logger.h b/src/libcharon/bus/listeners/file_logger.h
index bd443fdb8..e02a12c0c 100644
--- a/src/libcharon/bus/listeners/file_logger.h
+++ b/src/libcharon/bus/listeners/file_logger.h
@@ -52,9 +52,10 @@ struct file_logger_t {
/**
* Constructor to create a file_logger_t object.
*
- * @param out FILE to write to
- * @return file_logger_t object
+ * @param out FILE to write to
+ * @param time_format format of timestamp prefix, as in strftime()
+ * @return file_logger_t object
*/
-file_logger_t *file_logger_create(FILE *out);
+file_logger_t *file_logger_create(FILE *out, char *time_format);
#endif /** FILE_LOGGER_H_ @}*/
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
index 9a51a2ef4..e7873ee8c 100644
--- a/src/libcharon/bus/listeners/listener.h
+++ b/src/libcharon/bus/listeners/listener.h
@@ -110,13 +110,15 @@ struct listener_t {
*
* @param ike_sa IKE_SA the child sa belongs to
* @param child_sa CHILD_SA this keymat is used for
+ * @param initiator initiator of the CREATE_CHILD_SA exchange
* @param dh diffie hellman shared secret
* @param nonce_i initiators nonce
* @param nonce_r responders nonce
* @return TRUE to stay registered, FALSE to unregister
*/
bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
- diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
+ bool initiator, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r);
/**
* Hook called if an IKE_SA gets up or down.
@@ -173,6 +175,21 @@ struct listener_t {
*/
bool (*authorize)(listener_t *this, ike_sa_t *ike_sa,
bool final, bool *success);
+
+ /**
+ * CHILD_SA traffic selector narrowing hook.
+ *
+ * This hook is invoked for each CHILD_SA and allows plugins to modify
+ * the traffic selector list negotiated for this CHILD_SA.
+ *
+ * @param ike_sa IKE_SA the created CHILD_SA is created in
+ * @param child_sa CHILD_SA set up with these traffic selectors
+ * @param type type of hook getting invoked
+ * @param local list of local traffic selectors to narrow
+ * @param remote list of remote traffic selectors to narrow
+ */
+ bool (*narrow)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ narrow_hook_t type, linked_list_t *local, linked_list_t *remote);
};
#endif /** LISTENER_H_ @}*/
diff --git a/src/libcharon/bus/listeners/sys_logger.c b/src/libcharon/bus/listeners/sys_logger.c
index 11421ad05..5bc1d581a 100644
--- a/src/libcharon/bus/listeners/sys_logger.c
+++ b/src/libcharon/bus/listeners/sys_logger.c
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <string.h>
+#include <syslog.h>
#include "sys_logger.h"
diff --git a/src/libcharon/bus/listeners/sys_logger.h b/src/libcharon/bus/listeners/sys_logger.h
index 730890d68..58d4de529 100644
--- a/src/libcharon/bus/listeners/sys_logger.h
+++ b/src/libcharon/bus/listeners/sys_logger.h
@@ -21,8 +21,6 @@
#ifndef SYS_LOGGER_H_
#define SYS_LOGGER_H_
-#include <syslog.h>
-
#include <bus/listeners/listener.h>
typedef struct sys_logger_t sys_logger_t;
diff --git a/src/libcharon/config/auth_cfg.c b/src/libcharon/config/auth_cfg.c
deleted file mode 100644
index 94362c756..000000000
--- a/src/libcharon/config/auth_cfg.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Martin Willi
- * Copyright (C) 2008 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "auth_cfg.h"
-
-#include <daemon.h>
-#include <utils/linked_list.h>
-#include <utils/identification.h>
-#include <credentials/certificates/certificate.h>
-
-ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
- "RULE_IDENTITY",
- "RULE_AUTH_CLASS",
- "RULE_EAP_IDENTITY",
- "RULE_EAP_TYPE",
- "RULE_EAP_VENDOR",
- "RULE_CA_CERT",
- "RULE_IM_CERT",
- "RULE_SUBJECT_CERT",
- "RULE_CRL_VALIDATION",
- "RULE_OCSP_VALIDATION",
- "RULE_AC_GROUP",
- "HELPER_IM_CERT",
- "HELPER_SUBJECT_CERT",
- "HELPER_IM_HASH_URL",
- "HELPER_SUBJECT_HASH_URL",
-);
-
-typedef struct private_auth_cfg_t private_auth_cfg_t;
-
-/**
- * private data of item_set
- */
-struct private_auth_cfg_t {
-
- /**
- * public functions
- */
- auth_cfg_t public;
-
- /**
- * list of entry_t
- */
- linked_list_t *entries;
-};
-
-typedef struct entry_t entry_t;
-
-struct entry_t {
- /** rule type */
- auth_rule_t type;
- /** associated value */
- void *value;
-};
-
-/**
- * enumerator for auth_cfg_t.create_enumerator()
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** inner enumerator from linked_list_t */
- enumerator_t *inner;
- /** current entry */
- entry_t *current;
-} entry_enumerator_t;
-
-/**
- * enumerate function for item_enumerator_t
- */
-static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
-{
- entry_t *entry;
-
- if (this->inner->enumerate(this->inner, &entry))
- {
- this->current = entry;
- *type = entry->type;
- *value = entry->value;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * destroy function for item_enumerator_t
- */
-static void entry_enumerator_destroy(entry_enumerator_t *this)
-{
- this->inner->destroy(this->inner);
- free(this);
-}
-
-/**
- * Implementation of auth_cfg_t.create_enumerator.
- */
-static enumerator_t* create_enumerator(private_auth_cfg_t *this)
-{
- entry_enumerator_t *enumerator;
-
- enumerator = malloc_thing(entry_enumerator_t);
- enumerator->inner = this->entries->create_enumerator(this->entries);
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)entry_enumerator_destroy;
- enumerator->current = NULL;
- return &enumerator->public;
-}
-
-/**
- * Destroy the value associated with an entry
- */
-static void destroy_entry_value(entry_t *entry)
-{
- switch (entry->type)
- {
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- {
- identification_t *id = (identification_t*)entry->value;
- id->destroy(id);
- break;
- }
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- {
- certificate_t *cert = (certificate_t*)entry->value;
- cert->destroy(cert);
- break;
- }
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- {
- free(entry->value);
- break;
- }
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- break;
- }
-}
-
-/**
- * Implementation of auth_cfg_t.replace.
- */
-static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
- auth_rule_t type, ...)
-{
- if (enumerator->current)
- {
- va_list args;
-
- va_start(args, type);
-
- destroy_entry_value(enumerator->current);
- enumerator->current->type = type;
- switch (type)
- {
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- /* integer type */
- enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
- break;
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- /* pointer type */
- enumerator->current->value = va_arg(args, void*);
- break;
- }
- va_end(args);
- }
-}
-
-/**
- * Implementation of auth_cfg_t.get.
- */
-static void* get(private_auth_cfg_t *this, auth_rule_t type)
-{
- enumerator_t *enumerator;
- void *current_value, *best_value = NULL;
- auth_rule_t current_type;
- bool found = FALSE;
-
- enumerator = create_enumerator(this);
- while (enumerator->enumerate(enumerator, &current_type, &current_value))
- {
- if (type == current_type)
- {
- if (type == AUTH_RULE_CRL_VALIDATION ||
- type == AUTH_RULE_OCSP_VALIDATION)
- { /* for CRL/OCSP validation, always get() the highest value */
- if (!found || current_value > best_value)
- {
- best_value = current_value;
- }
- found = TRUE;
- continue;
- }
- best_value = current_value;
- found = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- if (found)
- {
- return best_value;
- }
- switch (type)
- {
- /* use some sane defaults if we don't find an entry */
- case AUTH_RULE_AUTH_CLASS:
- return (void*)AUTH_CLASS_ANY;
- case AUTH_RULE_EAP_TYPE:
- return (void*)EAP_NAK;
- case AUTH_RULE_EAP_VENDOR:
- return (void*)0;
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- return (void*)VALIDATION_FAILED;
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- default:
- return NULL;
- }
-}
-
-/**
- * Implementation of auth_cfg_t.add.
- */
-static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
-{
- entry_t *entry = malloc_thing(entry_t);
- va_list args;
-
- va_start(args, type);
- entry->type = type;
- switch (type)
- {
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- /* integer type */
- entry->value = (void*)(uintptr_t)va_arg(args, u_int);
- break;
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- /* pointer type */
- entry->value = va_arg(args, void*);
- break;
- }
- va_end(args);
- this->entries->insert_last(this->entries, entry);
-}
-
-/**
- * Implementation of auth_cfg_t.complies.
- */
-static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
- bool log_error)
-{
- enumerator_t *e1, *e2;
- bool success = TRUE;
- auth_rule_t t1, t2;
- void *value;
-
- e1 = constraints->create_enumerator(constraints);
- while (e1->enumerate(e1, &t1, &value))
- {
- switch (t1)
- {
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- {
- certificate_t *c1, *c2;
-
- c1 = (certificate_t*)value;
-
- success = FALSE;
- e2 = create_enumerator(this);
- while (e2->enumerate(e2, &t2, &c2))
- {
- if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
- c1->equals(c1, c2))
- {
- success = TRUE;
- }
- }
- e2->destroy(e2);
- if (!success && log_error)
- {
- DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated by CA '%Y'.", c1->get_subject(c1));
- }
- break;
- }
- case AUTH_RULE_SUBJECT_CERT:
- {
- certificate_t *c1, *c2;
-
- c1 = (certificate_t*)value;
- c2 = get(this, AUTH_RULE_SUBJECT_CERT);
- if (!c2 || !c1->equals(c1, c2))
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated with peer cert '%Y'.",
- c1->get_subject(c1));
- }
- }
- break;
- }
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- {
- cert_validation_t validated, required;
-
- required = (uintptr_t)value;
- validated = (uintptr_t)get(this, t1);
- switch (required)
- {
- case VALIDATION_FAILED:
- /* no constraint */
- break;
- case VALIDATION_SKIPPED:
- if (validated == VALIDATION_SKIPPED)
- {
- break;
- }
- /* FALL */
- case VALIDATION_GOOD:
- if (validated == VALIDATION_GOOD)
- {
- break;
- }
- /* FALL */
- default:
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint check failed: %N is %N, "
- "but requires at least %N", auth_rule_names,
- t1, cert_validation_names, validated,
- cert_validation_names, required);
- }
- break;
- }
- break;
- }
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- {
- identification_t *id1, *id2;
-
- id1 = (identification_t*)value;
- id2 = get(this, t1);
- if (!id2 || !id2->matches(id2, id1))
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
- " required ", t1 == AUTH_RULE_IDENTITY ? "" :
- "EAP ", id1);
- }
- }
- break;
- }
- case AUTH_RULE_AUTH_CLASS:
- {
- if ((uintptr_t)value != AUTH_CLASS_ANY &&
- (uintptr_t)value != (uintptr_t)get(this, t1))
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires %N authentication, "
- "but %N was used", auth_class_names, (uintptr_t)value,
- auth_class_names, (uintptr_t)get(this, t1));
- }
- }
- break;
- }
- case AUTH_RULE_EAP_TYPE:
- {
- if ((uintptr_t)value != (uintptr_t)get(this, t1))
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires %N, "
- "but %N was used", eap_type_names, (uintptr_t)value,
- eap_type_names, (uintptr_t)get(this, t1));
- }
- }
- break;
- }
- case AUTH_RULE_EAP_VENDOR:
- {
- if ((uintptr_t)value != (uintptr_t)get(this, t1))
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
- "but %d was used", (uintptr_t)value,
- (uintptr_t)get(this, t1));
- }
- }
- break;
- }
- case AUTH_RULE_AC_GROUP:
- {
- success = FALSE;
- if (log_error)
- {
- DBG1(DBG_CFG, "constraint check %N not implemented!",
- auth_rule_names, t1);
- }
- break;
- }
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- /* skip helpers */
- continue;
- }
- if (!success)
- {
- break;
- }
- }
- e1->destroy(e1);
- return success;
-}
-
-/**
- * Implementation of auth_cfg_t.merge.
- */
-static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
-{
- if (!other)
- { /* nothing to merge */
- return;
- }
- if (copy)
- {
- enumerator_t *enumerator;
- auth_rule_t type;
- void *value;
-
- enumerator = create_enumerator(other);
- while (enumerator->enumerate(enumerator, &type, &value))
- {
- switch (type)
- {
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- {
- certificate_t *cert = (certificate_t*)value;
-
- add(this, type, cert->get_ref(cert));
- break;
- }
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- {
- add(this, type, (uintptr_t)value);
- break;
- }
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- {
- identification_t *id = (identification_t*)value;
-
- add(this, type, id->clone(id));
- break;
- }
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- {
- add(this, type, strdup((char*)value));
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
- else
- {
- entry_t *entry;
-
- while (other->entries->remove_first(other->entries,
- (void**)&entry) == SUCCESS)
- {
- this->entries->insert_last(this->entries, entry);
- }
- }
-}
-
-/**
- * Implementation of auth_cfg_t.equals.
- */
-static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
-{
- enumerator_t *e1, *e2;
- entry_t *i1, *i2;
- bool equal = TRUE, found;
-
- if (this->entries->get_count(this->entries) !=
- other->entries->get_count(other->entries))
- {
- return FALSE;
- }
- e1 = this->entries->create_enumerator(this->entries);
- while (e1->enumerate(e1, &i1))
- {
- found = FALSE;
- e2 = other->entries->create_enumerator(other->entries);
- while (e2->enumerate(e2, &i2))
- {
- if (i1->type == i2->type)
- {
- switch (i1->type)
- {
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- {
- if (i1->value == i2->value)
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- {
- certificate_t *c1, *c2;
-
- c1 = (certificate_t*)i1->value;
- c2 = (certificate_t*)i2->value;
-
- if (c1->equals(c1, c2))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- {
- identification_t *id1, *id2;
-
- id1 = (identification_t*)i1->value;
- id2 = (identification_t*)i2->value;
-
- if (id1->equals(id1, id2))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- {
- if (streq(i1->value, i2->value))
- {
- found = TRUE;
- break;
- }
- continue;
- }
- }
- break;
- }
- }
- e2->destroy(e2);
- if (!found)
- {
- equal = FALSE;
- break;
- }
- }
- e1->destroy(e1);
- return equal;
-}
-
-/**
- * Implementation of auth_cfg_t.purge
- */
-static void purge(private_auth_cfg_t *this, bool keep_ca)
-{
- entry_t *entry;
- linked_list_t *cas;
-
- cas = linked_list_create();
- while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
- {
- if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
- {
- cas->insert_first(cas, entry);
- }
- else
- {
- destroy_entry_value(entry);
- free(entry);
- }
- }
- while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
- {
- this->entries->insert_first(this->entries, entry);
- }
- cas->destroy(cas);
-}
-
-/**
- * Implementation of auth_cfg_t.clone
- */
-static auth_cfg_t* clone_(private_auth_cfg_t *this)
-{
- enumerator_t *enumerator;
- auth_cfg_t *clone;
- entry_t *entry;
-
- clone = auth_cfg_create();
- enumerator = this->entries->create_enumerator(this->entries);
- while (enumerator->enumerate(enumerator, &entry))
- {
- switch (entry->type)
- {
- case AUTH_RULE_IDENTITY:
- case AUTH_RULE_EAP_IDENTITY:
- case AUTH_RULE_AC_GROUP:
- {
- identification_t *id = (identification_t*)entry->value;
- clone->add(clone, entry->type, id->clone(id));
- break;
- }
- case AUTH_RULE_CA_CERT:
- case AUTH_RULE_IM_CERT:
- case AUTH_RULE_SUBJECT_CERT:
- case AUTH_HELPER_IM_CERT:
- case AUTH_HELPER_SUBJECT_CERT:
- {
- certificate_t *cert = (certificate_t*)entry->value;
- clone->add(clone, entry->type, cert->get_ref(cert));
- break;
- }
- case AUTH_HELPER_IM_HASH_URL:
- case AUTH_HELPER_SUBJECT_HASH_URL:
- {
- clone->add(clone, entry->type, strdup(entry->value));
- break;
- }
- case AUTH_RULE_AUTH_CLASS:
- case AUTH_RULE_EAP_TYPE:
- case AUTH_RULE_EAP_VENDOR:
- case AUTH_RULE_CRL_VALIDATION:
- case AUTH_RULE_OCSP_VALIDATION:
- clone->add(clone, entry->type, (uintptr_t)entry->value);
- break;
- }
- }
- enumerator->destroy(enumerator);
- return clone;
-}
-
-/**
- * Implementation of auth_cfg_t.destroy
- */
-static void destroy(private_auth_cfg_t *this)
-{
- purge(this, FALSE);
- this->entries->destroy(this->entries);
- free(this);
-}
-
-/*
- * see header file
- */
-auth_cfg_t *auth_cfg_create()
-{
- private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
-
- this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
- this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
- this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
- this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
- this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
- this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
- this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
- this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
- this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
- this->public.destroy = (void(*)(auth_cfg_t*))destroy;
-
- this->entries = linked_list_create();
-
- return &this->public;
-}
-
diff --git a/src/libcharon/config/auth_cfg.h b/src/libcharon/config/auth_cfg.h
deleted file mode 100644
index 5e6215a4a..000000000
--- a/src/libcharon/config/auth_cfg.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Martin Willi
- * Copyright (C) 2008 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup auth_cfg auth_cfg
- * @{ @ingroup config
- */
-
-#ifndef AUTH_CFG_H_
-#define AUTH_CFG_H_
-
-#include <utils/enumerator.h>
-
-typedef struct auth_cfg_t auth_cfg_t;
-typedef enum auth_rule_t auth_rule_t;
-
-/**
- * Authentication config to use during authentication process.
- *
- * Each authentication config contains a set of rules. These rule-sets are used
- * in two ways:
- * - For configs specifying local authentication behavior, the rules define
- * which authentication method in which way.
- * - For configs specifying remote peer authentication, the rules define
- * constraints the peer has to fullfill.
- *
- * Additionally to the rules, there is a set of helper items. These are used
- * to transport credentials during the authentication process.
- */
-enum auth_rule_t {
-
- /** identity to use for IKEv2 authentication exchange, identification_t* */
- AUTH_RULE_IDENTITY,
- /** authentication class, auth_class_t */
- AUTH_RULE_AUTH_CLASS,
- /** EAP identity to use within EAP-Identity exchange, identification_t* */
- AUTH_RULE_EAP_IDENTITY,
- /** EAP type to propose for peer authentication, eap_type_t */
- AUTH_RULE_EAP_TYPE,
- /** EAP vendor for vendor specific type, u_int32_t */
- AUTH_RULE_EAP_VENDOR,
- /** certificate authority, certificate_t* */
- AUTH_RULE_CA_CERT,
- /** intermediate certificate in trustchain, certificate_t* */
- AUTH_RULE_IM_CERT,
- /** subject certificate, certificate_t* */
- AUTH_RULE_SUBJECT_CERT,
- /** result of a CRL validation, cert_validation_t */
- AUTH_RULE_CRL_VALIDATION,
- /** result of a OCSP validation, cert_validation_t */
- AUTH_RULE_OCSP_VALIDATION,
- /** subject is in attribute certificate group, identification_t* */
- AUTH_RULE_AC_GROUP,
-
- /** intermediate certificate, certificate_t* */
- AUTH_HELPER_IM_CERT,
- /** subject certificate, certificate_t* */
- AUTH_HELPER_SUBJECT_CERT,
- /** Hash and URL of a intermediate certificate, char* */
- AUTH_HELPER_IM_HASH_URL,
- /** Hash and URL of a end-entity certificate, char* */
- AUTH_HELPER_SUBJECT_HASH_URL,
-};
-
-/**
- * enum name for auth_rule_t.
- */
-extern enum_name_t *auth_rule_names;
-
-/**
- * Authentication/Authorization round.
- *
- * RFC4739 defines multiple authentication rounds. This class defines such
- * a round from a configuration perspective, either for the local or the remote
- * peer. Local config are called "rulesets", as they define how we authenticate.
- * Remote peer configs are called "constraits", they define what is needed to
- * complete the authentication round successfully.
- *
- * @verbatim
-
- [Repeat for each configuration]
- +--------------------------------------------------+
- | |
- | |
- | +----------+ IKE_AUTH +--------- + |
- | | config | -----------> | | |
- | | ruleset | | | |
- | +----------+ [ <----------- ] | | |
- | [ optional EAP ] | Peer | |
- | +----------+ [ -----------> ] | | |
- | | config | | | |
- | | constr. | <----------- | | |
- | +----------+ IKE_AUTH +--------- + |
- | |
- | |
- +--------------------------------------------------+
-
- @endverbatim
- *
- * Values for each items are either pointers (casted to void*) or short
- * integers (use uintptr_t cast).
- */
-struct auth_cfg_t {
-
- /**
- * Add an rule to the set.
- *
- * @param rule rule type
- * @param ... associated value to rule
- */
- void (*add)(auth_cfg_t *this, auth_rule_t rule, ...);
-
- /**
- * Get an rule value.
- *
- * @param rule rule type
- * @return bool if item has been found
- */
- void* (*get)(auth_cfg_t *this, auth_rule_t rule);
-
- /**
- * Create an enumerator over added rules.
- *
- * @return enumerator over (auth_rule_t, union{void*,uintpr_t})
- */
- enumerator_t* (*create_enumerator)(auth_cfg_t *this);
-
- /**
- * Replace an rule at enumerator position.
- *
- * @param pos enumerator position position
- * @param rule rule type
- * @param ... associated value to rule
- */
- void (*replace)(auth_cfg_t *this, enumerator_t *pos,
- auth_rule_t rule, ...);
-
- /**
- * Check if a used config fulfills a set of configured constraints.
- *
- * @param constraints required authorization rules
- * @param log_error wheter to log compliance errors
- * @return TRUE if this complies with constraints
- */
- bool (*complies)(auth_cfg_t *this, auth_cfg_t *constraints, bool log_error);
-
- /**
- * Merge items from other into this.
- *
- * @param other items to read for merge
- * @param copy TRUE to copy items, FALSE to move them
- */
- void (*merge)(auth_cfg_t *this, auth_cfg_t *other, bool copy);
-
- /**
- * Purge all rules in a config.
- *
- * @param keep_ca wheter to keep AUTH_RULE_CA_CERT entries
- */
- void (*purge)(auth_cfg_t *this, bool keep_ca);
-
- /**
- * Check two configs for equality.
- *
- * @param other other config to compaire against this
- * @return TRUE if auth infos identical
- */
- bool (*equals)(auth_cfg_t *this, auth_cfg_t *other);
-
- /**
- * Clone a authentication config, including all rules.
- *
- * @return cloned configuration
- */
- auth_cfg_t* (*clone)(auth_cfg_t *this);
-
- /**
- * Destroy a config with all associated rules/values.
- */
- void (*destroy)(auth_cfg_t *this);
-};
-
-/**
- * Create a authentication config.
- */
-auth_cfg_t *auth_cfg_create();
-
-#endif /** AUTH_CFG_H_ @}*/
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 8410b3fe5..70f38b285 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -17,6 +17,8 @@
#include "child_cfg.h"
+#include <stdint.h>
+
#include <daemon.h>
ENUM(action_names, ACTION_NONE, ACTION_RESTART,
@@ -112,6 +114,20 @@ struct private_child_cfg_t {
u_int32_t inactivity;
/**
+ * Reqid to install CHILD_SA with
+ */
+ u_int32_t reqid;
+
+ /**
+ * Optional mark to install inbound CHILD_SA with
+ */
+ mark_t mark_in;
+
+ /**
+ * Optional mark to install outbound CHILD_SA with
+ */
+ mark_t mark_out;
+ /**
* set up IPsec transport SA in MIPv6 proxy mode
*/
bool proxy_mode;
@@ -446,6 +462,22 @@ static u_int32_t get_inactivity(private_child_cfg_t *this)
}
/**
+ * Implementation of child_cfg_t.get_reqid.
+ */
+static u_int32_t get_reqid(private_child_cfg_t *this)
+{
+ return this->reqid;
+}
+
+/**
+ * Implementation of child_cfg_t.get_mark.
+ */
+static mark_t get_mark(private_child_cfg_t *this, bool inbound)
+{
+ return inbound ? this->mark_in : this->mark_out;
+}
+
+/**
* Implementation of child_cfg_t.set_mipv6_options.
*/
static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
@@ -506,7 +538,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp,
- u_int32_t inactivity)
+ u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark_in, mark_t *mark_out)
{
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
@@ -526,6 +559,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
this->public.set_mipv6_options = (void (*) (child_cfg_t*,bool,bool))set_mipv6_options;
this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity;
+ this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid;
+ this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark;
this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
@@ -539,6 +574,27 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
this->close_action = close_action;
this->use_ipcomp = ipcomp;
this->inactivity = inactivity;
+ this->reqid = reqid;
+
+ if (mark_in)
+ {
+ this->mark_in = *mark_in;
+ }
+ else
+ {
+ this->mark_in.value = 0;
+ this->mark_in.mask = 0;
+ }
+ if (mark_out)
+ {
+ this->mark_out = *mark_out;
+ }
+ else
+ {
+ this->mark_out.value = 0;
+ this->mark_out.mask = 0;
+ }
+
this->proxy_mode = FALSE;
this->install_policy = TRUE;
this->refcount = 1;
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index c6186ea36..d34835ead 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -26,6 +26,7 @@
typedef enum action_t action_t;
typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct lifetime_cfg_t lifetime_cfg_t;
+typedef struct mark_t mark_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
@@ -83,6 +84,16 @@ struct lifetime_cfg_t {
};
/**
+ * A mark_t defines an optional mark in a CHILD_SA.
+ */
+struct mark_t {
+ /** Mark value */
+ u_int32_t value;
+ /** Mark mask */
+ u_int32_t mask;
+};
+
+/**
* A child_cfg_t defines the config template for a CHILD_SA.
*
* After creation, proposals and traffic selectors may be added to the config.
@@ -239,6 +250,21 @@ struct child_cfg_t {
u_int32_t (*get_inactivity)(child_cfg_t *this);
/**
+ * Specific reqid to use for CHILD_SA
+ *
+ * @return reqid
+ */
+ u_int32_t (*get_reqid)(child_cfg_t *this);
+
+ /**
+ * Optional mark for CHILD_SA
+ *
+ * @param inbound TRUE for inbound, FALSE for outbound
+ * @return mark
+ */
+ mark_t (*get_mark)(child_cfg_t *this, bool inbound);
+
+ /**
* Sets two options needed for Mobile IPv6 interoperability
*
* @param proxy_mode use IPsec transport proxy mode (default FALSE)
@@ -299,12 +325,16 @@ struct child_cfg_t {
* @param close_action close action
* @param ipcomp use IPComp, if peer supports it
* @param inactivity inactivity timeout in s before closing a CHILD_SA
- * @return child_cfg_t object
+ * @param reqid specific reqid to use for CHILD_SA, 0 for auto assign
+ * @param mark_in optional inbound mark (can be NULL)
+ * @param mark_out optional outbound mark (can be NULL)
+ * @return child_cfg_t object
*/
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp,
- u_int32_t inactivity);
+ u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark_in, mark_t *mark_out);
#endif /** CHILD_CFG_H_ @}*/
diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h
index 6855276f8..723435cbb 100644
--- a/src/libcharon/config/peer_cfg.h
+++ b/src/libcharon/config/peer_cfg.h
@@ -36,7 +36,7 @@ typedef struct peer_cfg_t peer_cfg_t;
#include <config/child_cfg.h>
#include <sa/authenticators/authenticator.h>
#include <sa/authenticators/eap/eap_method.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
/**
* Certificate sending policy. This is also used for certificate
diff --git a/src/libcharon/credentials/credential_manager.c b/src/libcharon/credentials/credential_manager.c
deleted file mode 100644
index adea0b4be..000000000
--- a/src/libcharon/credentials/credential_manager.c
+++ /dev/null
@@ -1,1681 +0,0 @@
-/*
- * Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "credential_manager.h"
-
-#include <daemon.h>
-#include <threading/thread_value.h>
-#include <threading/mutex.h>
-#include <threading/rwlock.h>
-#include <utils/linked_list.h>
-#include <credentials/sets/cert_cache.h>
-#include <credentials/sets/auth_cfg_wrapper.h>
-#include <credentials/sets/ocsp_response_wrapper.h>
-#include <credentials/certificates/x509.h>
-#include <credentials/certificates/crl.h>
-#include <credentials/certificates/ocsp_request.h>
-#include <credentials/certificates/ocsp_response.h>
-
-typedef struct private_credential_manager_t private_credential_manager_t;
-
-/**
- * private data of credential_manager
- */
-struct private_credential_manager_t {
-
- /**
- * public functions
- */
- credential_manager_t public;
-
- /**
- * list of credential sets
- */
- linked_list_t *sets;
-
- /**
- * thread local set of credentials, linked_list_t with credential_set_t's
- */
- thread_value_t *local_sets;
-
- /**
- * trust relationship and certificate cache
- */
- cert_cache_t *cache;
-
- /**
- * certificates queued for persistent caching
- */
- linked_list_t *cache_queue;
-
- /**
- * read-write lock to sets list
- */
- rwlock_t *lock;
-
- /**
- * mutex for cache queue
- */
- mutex_t *queue_mutex;
-};
-
-/** data to pass to create_private_enumerator */
-typedef struct {
- private_credential_manager_t *this;
- key_type_t type;
- identification_t* keyid;
-} private_data_t;
-
-/** data to pass to create_cert_enumerator */
-typedef struct {
- private_credential_manager_t *this;
- certificate_type_t cert;
- key_type_t key;
- identification_t *id;
- bool trusted;
-} cert_data_t;
-
-/** data to pass to create_cdp_enumerator */
-typedef struct {
- private_credential_manager_t *this;
- certificate_type_t type;
- identification_t *id;
-} cdp_data_t;
-
-/** data to pass to create_shared_enumerator */
-typedef struct {
- private_credential_manager_t *this;
- shared_key_type_t type;
- identification_t *me;
- identification_t *other;
-} shared_data_t;
-
-/** enumerator over local and global sets */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** enumerator over global sets */
- enumerator_t *global;
- /** enumerator over local sets */
- enumerator_t *local;
-} sets_enumerator_t;
-
-/**
- * destroy a sets_enumerator_t
- */
-static void sets_enumerator_destroy(sets_enumerator_t *this)
-{
- DESTROY_IF(this->global);
- DESTROY_IF(this->local);
- free(this);
-}
-
-/**
- * sets_enumerator_t.enumerate
- */
-static bool sets_enumerator_enumerate(sets_enumerator_t *this,
- credential_set_t **set)
-{
- if (this->global)
- {
- if (this->global->enumerate(this->global, set))
- {
- return TRUE;
- }
- /* end of global sets, look for local */
- this->global->destroy(this->global);
- this->global = NULL;
- }
- if (this->local)
- {
- return this->local->enumerate(this->local, set);
- }
- return FALSE;
-}
-
-/**
- * create an enumerator over both, global and local sets
- */
-static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
-{
- linked_list_t *local;
- sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t);
-
- enumerator->public.enumerate = (void*)sets_enumerator_enumerate;
- enumerator->public.destroy = (void*)sets_enumerator_destroy;
- enumerator->global = this->sets->create_enumerator(this->sets);
- enumerator->local = NULL;
- local = this->local_sets->get(this->local_sets);
- if (local)
- {
- enumerator->local = local->create_enumerator(local);
- }
- return &enumerator->public;
-}
-
-/**
- * cleanup function for cert data
- */
-static void destroy_cert_data(cert_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * enumerator constructor for certificates
- */
-static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
-{
- return set->create_cert_enumerator(set, data->cert, data->key,
- data->id, data->trusted);
-}
-
-/**
- * Implementation of credential_manager_t.create_cert_enumerator.
- */
-static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
- certificate_type_t certificate, key_type_t key,
- identification_t *id, bool trusted)
-{
- cert_data_t *data = malloc_thing(cert_data_t);
- data->this = this;
- data->cert = certificate;
- data->key = key;
- data->id = id;
- data->trusted = trusted;
-
- this->lock->read_lock(this->lock);
- return enumerator_create_nested(create_sets_enumerator(this),
- (void*)create_cert, data,
- (void*)destroy_cert_data);
-}
-
-/**
- * Implementation of credential_manager_t.get_cert.
- */
-static certificate_t *get_cert(private_credential_manager_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- certificate_t *current, *found = NULL;
- enumerator_t *enumerator;
-
- enumerator = create_cert_enumerator(this, cert, key, id, trusted);
- if (enumerator->enumerate(enumerator, &current))
- {
- /* TODO: best match? order by keyid, subject, sualtname */
- found = current->get_ref(current);
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-
-/**
- * cleanup function for cdp data
- */
-static void destroy_cdp_data(cdp_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * enumerator constructor for CDPs
- */
-static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
-{
- return set->create_cdp_enumerator(set, data->type, data->id);
-}
-/**
- * Implementation of credential_manager_t.create_cdp_enumerator.
- */
-static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
- certificate_type_t type, identification_t *id)
-{
- cdp_data_t *data = malloc_thing(cdp_data_t);
- data->this = this;
- data->type = type;
- data->id = id;
-
- this->lock->read_lock(this->lock);
- return enumerator_create_nested(create_sets_enumerator(this),
- (void*)create_cdp, data,
- (void*)destroy_cdp_data);
-}
-
-/**
- * cleanup function for private data
- */
-static void destroy_private_data(private_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * enumerator constructor for private keys
- */
-static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
-{
- return set->create_private_enumerator(set, data->type, data->keyid);
-}
-
-/**
- * Implementation of credential_manager_t.create_private_enumerator.
- */
-static enumerator_t* create_private_enumerator(
- private_credential_manager_t *this,
- key_type_t key, identification_t *keyid)
-{
- private_data_t *data;
-
- data = malloc_thing(private_data_t);
- data->this = this;
- data->type = key;
- data->keyid = keyid;
- this->lock->read_lock(this->lock);
- return enumerator_create_nested(create_sets_enumerator(this),
- (void*)create_private, data,
- (void*)destroy_private_data);
-}
-
-/**
- * Implementation of credential_manager_t.get_private_by_keyid.
- */
-static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
- key_type_t key, identification_t *keyid)
-{
- private_key_t *found = NULL;
- enumerator_t *enumerator;
-
- enumerator = create_private_enumerator(this, key, keyid);
- if (enumerator->enumerate(enumerator, &found))
- {
- found->get_ref(found);
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-/**
- * cleanup function for shared data
- */
-static void destroy_shared_data(shared_data_t *data)
-{
- data->this->lock->unlock(data->this->lock);
- free(data);
-}
-
-/**
- * enumerator constructor for shared keys
- */
-static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
-{
- return set->create_shared_enumerator(set, data->type, data->me, data->other);
-}
-
-/**
- * Implementation of credential_manager_t.create_shared_enumerator.
- */
-static enumerator_t *create_shared_enumerator(private_credential_manager_t *this,
- shared_key_type_t type,
- identification_t *me, identification_t *other)
-{
- shared_data_t *data = malloc_thing(shared_data_t);
- data->this = this;
- data->type = type;
- data->me = me;
- data->other = other;
-
- this->lock->read_lock(this->lock);
- return enumerator_create_nested(create_sets_enumerator(this),
- (void*)create_shared, data,
- (void*)destroy_shared_data);
-}
-
-/**
- * Implementation of credential_manager_t.get_shared.
- */
-static shared_key_t *get_shared(private_credential_manager_t *this,
- shared_key_type_t type, identification_t *me,
- identification_t *other)
-{
- shared_key_t *current, *found = NULL;
- id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
- id_match_t *match_me, *match_other;
- enumerator_t *enumerator;
-
- enumerator = create_shared_enumerator(this, type, me, other);
- while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
- {
- if (match_other > best_other ||
- (match_other == best_other && match_me > best_me))
- {
- DESTROY_IF(found);
- found = current->get_ref(current);
- best_me = match_me;
- best_other = match_other;
- }
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-/**
- * add a credential set to the thread local list
- */
-static void add_local_set(private_credential_manager_t *this,
- credential_set_t *set)
-{
- linked_list_t *sets;
-
- sets = this->local_sets->get(this->local_sets);
- if (!sets)
- { /* first invocation */
- sets = linked_list_create();
- this->local_sets->set(this->local_sets, sets);
- }
- sets->insert_last(sets, set);
-}
-
-/**
- * remove a credential set from the thread local list
- */
-static void remove_local_set(private_credential_manager_t *this,
- credential_set_t *set)
-{
- linked_list_t *sets;
-
- sets = this->local_sets->get(this->local_sets);
- sets->remove(sets, set, NULL);
-}
-
-/**
- * Implementation of credential_manager_t.cache_cert.
- */
-static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
-{
- credential_set_t *set;
- enumerator_t *enumerator;
-
- if (this->lock->try_write_lock(this->lock))
- {
- enumerator = this->sets->create_enumerator(this->sets);
- while (enumerator->enumerate(enumerator, &set))
- {
- set->cache_cert(set, cert);
- }
- enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
- }
- else
- { /* we can't cache now as other threads are active, queue for later */
- this->queue_mutex->lock(this->queue_mutex);
- this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
- this->queue_mutex->unlock(this->queue_mutex);
- }
-}
-
-/**
- * Try to cache certificates queued for caching
- */
-static void cache_queue(private_credential_manager_t *this)
-{
- credential_set_t *set;
- certificate_t *cert;
- enumerator_t *enumerator;
-
- this->queue_mutex->lock(this->queue_mutex);
- if (this->cache_queue->get_count(this->cache_queue) > 0 &&
- this->lock->try_write_lock(this->lock))
- {
- while (this->cache_queue->remove_last(this->cache_queue,
- (void**)&cert) == SUCCESS)
- {
- enumerator = this->sets->create_enumerator(this->sets);
- while (enumerator->enumerate(enumerator, &set))
- {
- set->cache_cert(set, cert);
- }
- enumerator->destroy(enumerator);
- cert->destroy(cert);
- }
- this->lock->unlock(this->lock);
- }
- this->queue_mutex->unlock(this->queue_mutex);
-}
-
-/**
- * forward declaration
- */
-static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
- key_type_t type, identification_t *id, bool crl, bool ocsp);
-
-/**
- * Do an OCSP request
- */
-static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
- certificate_t *subject, certificate_t *issuer)
-{
- certificate_t *request, *response;
- chunk_t send, receive;
-
- /* TODO: requestor name, signature */
- request = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
- BUILD_CA_CERT, issuer,
- BUILD_CERT, subject, BUILD_END);
- if (!request)
- {
- DBG1(DBG_CFG, "generating ocsp request failed");
- return NULL;
- }
-
- send = request->get_encoding(request);
- request->destroy(request);
-
- DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, &receive,
- FETCH_REQUEST_DATA, send,
- FETCH_REQUEST_TYPE, "application/ocsp-request",
- FETCH_END) != SUCCESS)
- {
- DBG1(DBG_CFG, "ocsp request to %s failed", url);
- chunk_free(&send);
- return NULL;
- }
- chunk_free(&send);
-
- response = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
- BUILD_BLOB_ASN1_DER, receive, BUILD_END);
- chunk_free(&receive);
- if (!response)
- {
- DBG1(DBG_CFG, "parsing ocsp response failed");
- return NULL;
- }
- return response;
-}
-
-/**
- * check the signature of an OCSP response
- */
-static bool verify_ocsp(private_credential_manager_t *this,
- ocsp_response_t *response)
-{
- certificate_t *issuer, *subject;
- identification_t *responder;
- ocsp_response_wrapper_t *wrapper;
- enumerator_t *enumerator;
- bool verified = FALSE;
-
- wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
- add_local_set(this, &wrapper->set);
-
- subject = &response->certificate;
- responder = subject->get_issuer(subject);
- enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE);
- while (enumerator->enumerate(enumerator, &issuer, NULL))
- {
- if (this->cache->issued_by(this->cache, subject, issuer))
- {
- DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
- issuer->get_subject(issuer));
- verified = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- remove_local_set(this, &wrapper->set);
- wrapper->destroy(wrapper);
- return verified;
-}
-
-/**
- * Get the better of two OCSP responses, and check for usable OCSP info
- */
-static certificate_t *get_better_ocsp(private_credential_manager_t *this,
- certificate_t *cand, certificate_t *best,
- x509_t *subject, x509_t *issuer,
- cert_validation_t *valid, bool cache)
-{
- ocsp_response_t *response;
- time_t revocation, this_update, next_update, valid_until;
- crl_reason_t reason;
- bool revoked = FALSE;
-
- response = (ocsp_response_t*)cand;
-
- /* check ocsp signature */
- if (!verify_ocsp(this, response))
- {
- DBG1(DBG_CFG, "ocsp response verification failed");
- cand->destroy(cand);
- return best;
- }
- /* check if response contains our certificate */
- switch (response->get_status(response, subject, issuer, &revocation, &reason,
- &this_update, &next_update))
- {
- case VALIDATION_REVOKED:
- /* subject has been revoked by a valid OCSP response */
- DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
- &revocation, TRUE, crl_reason_names, reason);
- revoked = TRUE;
- break;
- case VALIDATION_GOOD:
- /* results in either good or stale */
- break;
- default:
- case VALIDATION_FAILED:
- /* candidate unusable, does not contain our cert */
- DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
- cand->destroy(cand);
- return best;
- }
-
- /* select the better of the two responses */
- if (best == NULL || cand->is_newer(cand, best))
- {
- DESTROY_IF(best);
- best = cand;
- if (best->get_validity(best, NULL, NULL, &valid_until))
- {
- DBG1(DBG_CFG, " ocsp response is valid: until %T",
- &valid_until, FALSE);
- *valid = VALIDATION_GOOD;
- if (cache)
- { /* cache non-stale only, stale certs get refetched */
- cache_cert(this, best);
- }
- }
- else
- {
- DBG1(DBG_CFG, " ocsp response is stale: since %T",
- &valid_until, FALSE);
- *valid = VALIDATION_STALE;
- }
- }
- else
- {
- *valid = VALIDATION_STALE;
- cand->destroy(cand);
- }
- if (revoked)
- { /* revoked always counts, even if stale */
- *valid = VALIDATION_REVOKED;
- }
- return best;
-}
-
-/**
- * validate a x509 certificate using OCSP
- */
-static cert_validation_t check_ocsp(private_credential_manager_t *this,
- x509_t *subject, x509_t *issuer,
- auth_cfg_t *auth)
-{
- enumerator_t *enumerator;
- cert_validation_t valid = VALIDATION_SKIPPED;
- certificate_t *best = NULL, *current;
- identification_t *keyid = NULL;
- public_key_t *public;
- chunk_t chunk;
- char *uri = NULL;
-
- /** lookup cache for valid OCSP responses */
- enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
- KEY_ANY, NULL, FALSE);
- while (enumerator->enumerate(enumerator, &current))
- {
- current->get_ref(current);
- best = get_better_ocsp(this, current, best, subject, issuer,
- &valid, FALSE);
- if (best && valid != VALIDATION_STALE)
- {
- DBG1(DBG_CFG, " using cached ocsp response");
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- /* derive the authorityKeyIdentifier from the issuer's public key */
- current = &issuer->interface;
- public = current->get_public_key(current);
- if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
- {
- keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
- }
- /** fetch from configured OCSP responder URLs */
- if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
- {
- enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
- while (enumerator->enumerate(enumerator, &uri))
- {
- current = fetch_ocsp(this, uri, &subject->interface,
- &issuer->interface);
- if (current)
- {
- best = get_better_ocsp(this, current, best, subject, issuer,
- &valid, TRUE);
- if (best && valid != VALIDATION_STALE)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
- DESTROY_IF(public);
- DESTROY_IF(keyid);
-
- /* fallback to URL fetching from subject certificate's URIs */
- if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
- {
- enumerator = subject->create_ocsp_uri_enumerator(subject);
- while (enumerator->enumerate(enumerator, &uri))
- {
- current = fetch_ocsp(this, uri, &subject->interface,
- &issuer->interface);
- if (current)
- {
- best = get_better_ocsp(this, current, best, subject, issuer,
- &valid, TRUE);
- if (best && valid != VALIDATION_STALE)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
- /* an uri was found, but no result. switch validation state to failed */
- if (valid == VALIDATION_SKIPPED && uri)
- {
- valid = VALIDATION_FAILED;
- }
- if (auth)
- {
- auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
- if (valid == VALIDATION_GOOD)
- { /* successful OCSP check fulfills also CRL constraint */
- auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
- }
- }
- DESTROY_IF(best);
- return valid;
-}
-
-/**
- * fetch a CRL from an URL
- */
-static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
-{
- certificate_t *crl;
- chunk_t chunk;
-
- DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
- {
- DBG1(DBG_CFG, "crl fetching failed");
- return NULL;
- }
- crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
- BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
- chunk_free(&chunk);
- if (!crl)
- {
- DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
- return NULL;
- }
- return crl;
-}
-
-/**
- * check the signature of an CRL
- */
-static bool verify_crl(private_credential_manager_t *this, certificate_t *crl)
-{
- certificate_t *issuer;
- enumerator_t *enumerator;
- bool verified = FALSE;
-
- enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl),
- FALSE, FALSE);
- while (enumerator->enumerate(enumerator, &issuer, NULL))
- {
- if (this->cache->issued_by(this->cache, crl, issuer))
- {
- DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
- issuer->get_subject(issuer));
- verified = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- return verified;
-}
-
-/**
- * Get the better of two CRLs, and check for usable CRL info
- */
-static certificate_t *get_better_crl(private_credential_manager_t *this,
- certificate_t *cand, certificate_t *best,
- x509_t *subject, x509_t *issuer,
- cert_validation_t *valid, bool cache)
-{
- enumerator_t *enumerator;
- time_t revocation, valid_until;
- crl_reason_t reason;
- chunk_t serial;
- crl_t *crl;
-
- /* check CRL signature */
- if (!verify_crl(this, cand))
- {
- DBG1(DBG_CFG, "crl response verification failed");
- cand->destroy(cand);
- return best;
- }
-
- crl = (crl_t*)cand;
- enumerator = crl->create_enumerator(crl);
- while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
- {
- if (chunk_equals(serial, subject->get_serial(subject)))
- {
- DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
- &revocation, TRUE, crl_reason_names, reason);
- *valid = VALIDATION_REVOKED;
- enumerator->destroy(enumerator);
- DESTROY_IF(best);
- return cand;
- }
- }
- enumerator->destroy(enumerator);
-
- /* select the better of the two CRLs */
- if (best == NULL || cand->is_newer(cand, best))
- {
- DESTROY_IF(best);
- best = cand;
- if (best->get_validity(best, NULL, NULL, &valid_until))
- {
- DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
- *valid = VALIDATION_GOOD;
- if (cache)
- { /* we cache non-stale crls only, as a stale crls are refetched */
- cache_cert(this, best);
- }
- }
- else
- {
- DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
- *valid = VALIDATION_STALE;
- }
- }
- else
- {
- *valid = VALIDATION_STALE;
- cand->destroy(cand);
- }
- return best;
-}
-
-/**
- * validate a x509 certificate using CRL
- */
-static cert_validation_t check_crl(private_credential_manager_t *this,
- x509_t *subject, x509_t *issuer,
- auth_cfg_t *auth)
-{
- cert_validation_t valid = VALIDATION_SKIPPED;
- identification_t *keyid = NULL;
- certificate_t *best = NULL;
- certificate_t *current;
- public_key_t *public;
- enumerator_t *enumerator;
- chunk_t chunk;
- char *uri = NULL;
-
- /* derive the authorityKeyIdentifier from the issuer's public key */
- current = &issuer->interface;
- public = current->get_public_key(current);
- if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
- {
- keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
-
- /* find a cached crl by authorityKeyIdentifier */
- enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY,
- keyid, FALSE);
- while (enumerator->enumerate(enumerator, &current))
- {
- current->get_ref(current);
- best = get_better_crl(this, current, best, subject, issuer,
- &valid, FALSE);
- if (best && valid != VALIDATION_STALE)
- {
- DBG1(DBG_CFG, " using cached crl");
- break;
- }
- }
- enumerator->destroy(enumerator);
-
- /* fallback to fetching crls from credential sets cdps */
- if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
- {
- enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid);
-
- while (enumerator->enumerate(enumerator, &uri))
- {
- current = fetch_crl(this, uri);
- if (current)
- {
- best = get_better_crl(this, current, best, subject, issuer,
- &valid, TRUE);
- if (best && valid != VALIDATION_STALE)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
- keyid->destroy(keyid);
- }
- DESTROY_IF(public);
-
- /* fallback to fetching crls from cdps from subject's certificate */
- if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
- {
- enumerator = subject->create_crl_uri_enumerator(subject);
-
- while (enumerator->enumerate(enumerator, &uri))
- {
- current = fetch_crl(this, uri);
- if (current)
- {
- best = get_better_crl(this, current, best, subject, issuer,
- &valid, TRUE);
- if (best && valid != VALIDATION_STALE)
- {
- break;
- }
- }
- }
- enumerator->destroy(enumerator);
- }
-
- /* an uri was found, but no result. switch validation state to failed */
- if (valid == VALIDATION_SKIPPED && uri)
- {
- valid = VALIDATION_FAILED;
- }
- if (auth)
- {
- if (valid == VALIDATION_SKIPPED)
- { /* if we skipped CRL validation, we use the result of OCSP for
- * constraint checking */
- auth->add(auth, AUTH_RULE_CRL_VALIDATION,
- auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
- }
- else
- {
- auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
- }
- }
- DESTROY_IF(best);
- return valid;
-}
-
-/**
- * check a certificate for optional IP address block constraints
- */
-static bool check_ip_addr_block_constraints(x509_t *subject, x509_t *issuer)
-{
- bool subject_constraint = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS;
- bool issuer_constraint = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS;
- bool contained = TRUE;
-
- enumerator_t *subject_enumerator, *issuer_enumerator;
- traffic_selector_t *subject_ts, *issuer_ts;
-
- if (!subject_constraint && !issuer_constraint)
- {
- return TRUE;
- }
- if (!subject_constraint)
- {
- DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
- return FALSE;
- }
- if (!issuer_constraint)
- {
- DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension");
- return FALSE;
- }
- subject_enumerator = subject->create_ipAddrBlock_enumerator(subject);
- while (subject_enumerator->enumerate(subject_enumerator, &subject_ts))
- {
- contained = FALSE;
-
- issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer);
- while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts))
- {
- if (subject_ts->is_contained_in(subject_ts, issuer_ts))
- {
- DBG2(DBG_CFG, " subject address block %R is contained in "
- "issuer address block %R", subject_ts, issuer_ts);
- contained = TRUE;
- break;
- }
- }
- issuer_enumerator->destroy(issuer_enumerator);
- if (!contained)
- {
- DBG1(DBG_CFG, "subject address block %R is not contained in any "
- "issuer address block", subject_ts);
- break;
- }
- }
- subject_enumerator->destroy(subject_enumerator);
- return contained;
-}
-
-/**
- * check a certificate for its lifetime
- */
-static bool check_certificate(private_credential_manager_t *this,
- certificate_t *subject, certificate_t *issuer,
- bool crl, bool ocsp, auth_cfg_t *auth)
-{
- time_t not_before, not_after;
-
- if (!subject->get_validity(subject, NULL, &not_before, &not_after))
- {
- DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
- return FALSE;
- }
- if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
- {
- DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
- return FALSE;
- }
- if (issuer->get_type(issuer) == CERT_X509 &&
- subject->get_type(subject) == CERT_X509)
- {
- if (!check_ip_addr_block_constraints((x509_t*)subject, (x509_t*)issuer))
- {
- return FALSE;
- }
- if (ocsp || crl)
- {
- DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
- subject->get_subject(subject));
- }
- if (ocsp)
- {
- switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
- {
- case VALIDATION_GOOD:
- DBG1(DBG_CFG, "certificate status is good");
- return TRUE;
- case VALIDATION_REVOKED:
- /* has already been logged */
- return FALSE;
- case VALIDATION_SKIPPED:
- DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
- break;
- case VALIDATION_STALE:
- DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
- break;
- case VALIDATION_FAILED:
- DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
- break;
- }
- }
- if (crl)
- {
- switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
- {
- case VALIDATION_GOOD:
- DBG1(DBG_CFG, "certificate status is good");
- return TRUE;
- case VALIDATION_REVOKED:
- /* has already been logged */
- return FALSE;
- case VALIDATION_FAILED:
- case VALIDATION_SKIPPED:
- DBG1(DBG_CFG, "certificate status is not available");
- break;
- case VALIDATION_STALE:
- DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
- break;
- }
- }
- }
- return TRUE;
-}
-
-/**
- * Get a trusted certificate from a credential set
- */
-static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
- key_type_t type, identification_t *id)
-{
- certificate_t *subject;
- public_key_t *public;
-
- subject = get_cert(this, CERT_ANY, type, id, TRUE);
- if (!subject)
- {
- return NULL;
- }
- public = subject->get_public_key(subject);
- if (!public)
- {
- subject->destroy(subject);
- return NULL;
- }
- public->destroy(public);
- return subject;
-}
-
-/**
- * Get the issuing certificate of a subject certificate
- */
-static certificate_t *get_issuer_cert(private_credential_manager_t *this,
- certificate_t *subject, bool trusted)
-{
- enumerator_t *enumerator;
- certificate_t *issuer = NULL, *candidate;
-
- enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
- subject->get_issuer(subject), trusted);
- while (enumerator->enumerate(enumerator, &candidate))
- {
- if (this->cache->issued_by(this->cache, subject, candidate))
- {
- issuer = candidate->get_ref(candidate);
- break;
- }
- }
- enumerator->destroy(enumerator);
- return issuer;
-}
-
-/**
- * try to verify the trust chain of subject, return TRUE if trusted
- */
-static bool verify_trust_chain(private_credential_manager_t *this,
- certificate_t *subject, auth_cfg_t *result,
- bool trusted, bool crl, bool ocsp)
-{
- certificate_t *current, *issuer;
- x509_t *x509;
- auth_cfg_t *auth;
- int pathlen, pathlen_constraint;
-
- auth = auth_cfg_create();
- current = subject->get_ref(subject);
-
- for (pathlen = 0; pathlen <= X509_MAX_PATH_LEN; pathlen++)
- {
- issuer = get_issuer_cert(this, current, TRUE);
- if (issuer)
- {
- /* accept only self-signed CAs as trust anchor */
- if (this->cache->issued_by(this->cache, issuer, issuer))
- {
- auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
- DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
- issuer->get_subject(issuer));
- trusted = TRUE;
- }
- else
- {
- auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
- DBG1(DBG_CFG, " using trusted intermediate ca certificate "
- "\"%Y\"", issuer->get_subject(issuer));
- }
- }
- else
- {
- issuer = get_issuer_cert(this, current, FALSE);
- if (issuer)
- {
- if (current->equals(current, issuer))
- {
- DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
- current->get_subject(current));
- issuer->destroy(issuer);
- break;
- }
- auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
- DBG1(DBG_CFG, " using untrusted intermediate certificate "
- "\"%Y\"", issuer->get_subject(issuer));
- }
- else
- {
- DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
- current->get_subject(current));
- break;
- }
- }
- if (!check_certificate(this, current, issuer, crl, ocsp,
- current == subject ? auth : NULL))
- {
- trusted = FALSE;
- issuer->destroy(issuer);
- break;
- }
-
- /* check path length constraint */
- x509 = (x509_t*)issuer;
- pathlen_constraint = x509->get_pathLenConstraint(x509);
- if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
- pathlen > pathlen_constraint)
- {
- DBG1(DBG_CFG, "path length of %d violates constraint of %d",
- pathlen, pathlen_constraint);
- trusted = FALSE;
- issuer->destroy(issuer);
- break;
- }
- current->destroy(current);
- current = issuer;
- if (trusted)
- {
- DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
- pathlen);
- break;
- }
- }
- current->destroy(current);
- if (pathlen > X509_MAX_PATH_LEN)
- {
- DBG1(DBG_CFG, "maximum path length of %d exceeded", X509_MAX_PATH_LEN);
- }
- if (trusted)
- {
- result->merge(result, auth, FALSE);
- }
- auth->destroy(auth);
- return trusted;
-}
-
-/**
- * enumerator for trusted certificates
- */
-typedef struct {
- /** implements enumerator_t interface */
- enumerator_t public;
- /** enumerator over candidate peer certificates */
- enumerator_t *candidates;
- /** reference to the credential_manager */
- private_credential_manager_t *this;
- /** type of the requested key */
- key_type_t type;
- /** identity the requested key belongs to */
- identification_t *id;
- /** TRUE to do CRL checking */
- bool crl;
- /** TRUE to do OCSP checking */
- bool ocsp;
- /** pretrusted certificate we have served at first invocation */
- certificate_t *pretrusted;
- /** currently enumerating auth config */
- auth_cfg_t *auth;
-} trusted_enumerator_t;
-
-/**
- * Implements trusted_enumerator_t.enumerate
- */
-static bool trusted_enumerate(trusted_enumerator_t *this,
- certificate_t **cert, auth_cfg_t **auth)
-{
- certificate_t *current;
-
- DESTROY_IF(this->auth);
- this->auth = auth_cfg_create();
-
- if (!this->candidates)
- {
- /* first invocation, build enumerator for next one */
- this->candidates = create_cert_enumerator(this->this, CERT_ANY,
- this->type, this->id, FALSE);
- /* check if we have a trusted certificate for that peer */
- this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
- if (this->pretrusted)
- {
- /* if we find a trusted self signed certificate, we just accept it.
- * However, in order to fulfill authorization rules, we try to build
- * the trust chain if it is not self signed */
- if (this->this->cache->issued_by(this->this->cache,
- this->pretrusted, this->pretrusted) ||
- verify_trust_chain(this->this, this->pretrusted, this->auth,
- TRUE, this->crl, this->ocsp))
- {
- this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
- this->pretrusted->get_ref(this->pretrusted));
- DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
- this->pretrusted->get_subject(this->pretrusted));
- *cert = this->pretrusted;
- if (auth)
- {
- *auth = this->auth;
- }
- return TRUE;
- }
- }
- }
- /* try to verify the trust chain for each certificate found */
- while (this->candidates->enumerate(this->candidates, &current))
- {
- if (this->pretrusted &&
- this->pretrusted->equals(this->pretrusted, current))
- { /* skip pretrusted certificate we already served */
- continue;
- }
-
- DBG1(DBG_CFG, " using certificate \"%Y\"",
- current->get_subject(current));
- if (verify_trust_chain(this->this, current, this->auth, FALSE,
- this->crl, this->ocsp))
- {
- *cert = current;
- if (auth)
- {
- *auth = this->auth;
- }
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * Implements trusted_enumerator_t.destroy
- */
-static void trusted_destroy(trusted_enumerator_t *this)
-{
- DESTROY_IF(this->pretrusted);
- DESTROY_IF(this->auth);
- DESTROY_IF(this->candidates);
- free(this);
-}
-
-/**
- * create an enumerator over trusted certificates and their trustchain
- */
-static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
- key_type_t type, identification_t *id, bool crl, bool ocsp)
-{
- trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
-
- enumerator->public.enumerate = (void*)trusted_enumerate;
- enumerator->public.destroy = (void*)trusted_destroy;
-
- enumerator->candidates = NULL;
- enumerator->this = this;
- enumerator->type = type;
- enumerator->id = id;
- enumerator->crl = crl;
- enumerator->ocsp = ocsp;
- enumerator->pretrusted = NULL;
- enumerator->auth = NULL;
-
- return &enumerator->public;
-}
-
-/**
- * enumerator for public keys
- */
-typedef struct {
- /** implements enumerator_t interface */
- enumerator_t public;
- /** enumerator over candidate peer certificates */
- enumerator_t *inner;
- /** reference to the credential_manager */
- private_credential_manager_t *this;
- /** currently enumerating key */
- public_key_t *current;
- /** credset wrapper around auth config */
- auth_cfg_wrapper_t *wrapper;
-} public_enumerator_t;
-
-/**
- * Implements public_enumerator_t.enumerate
- */
-static bool public_enumerate(public_enumerator_t *this,
- public_key_t **key, auth_cfg_t **auth)
-{
- certificate_t *cert;
-
- while (this->inner->enumerate(this->inner, &cert, auth))
- {
- DESTROY_IF(this->current);
- this->current = cert->get_public_key(cert);
- if (this->current)
- {
- *key = this->current;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * Implements public_enumerator_t.destroy
- */
-static void public_destroy(public_enumerator_t *this)
-{
- DESTROY_IF(this->current);
- this->inner->destroy(this->inner);
- if (this->wrapper)
- {
- remove_local_set(this->this, &this->wrapper->set);
- this->wrapper->destroy(this->wrapper);
- }
- this->this->lock->unlock(this->this->lock);
-
- /* check for delayed certificate cache queue */
- cache_queue(this->this);
- free(this);
-}
-
-/**
- * Implementation of credential_manager_t.create_public_enumerator.
- */
-static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
- key_type_t type, identification_t *id, auth_cfg_t *auth)
-{
- public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
-
- enumerator->public.enumerate = (void*)public_enumerate;
- enumerator->public.destroy = (void*)public_destroy;
- enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE);
- enumerator->this = this;
- enumerator->current = NULL;
- enumerator->wrapper = NULL;
- if (auth)
- {
- enumerator->wrapper = auth_cfg_wrapper_create(auth);
- add_local_set(this, &enumerator->wrapper->set);
- }
- this->lock->read_lock(this->lock);
- return &enumerator->public;
-}
-
-/**
- * Check if a certificate's keyid is contained in the auth helper
- */
-static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
-{
- enumerator_t *enumerator;
- identification_t *value;
- auth_rule_t type;
- bool found = FALSE;
-
- enumerator = auth->create_enumerator(auth);
- while (enumerator->enumerate(enumerator, &type, &value))
- {
- if (type == AUTH_RULE_CA_CERT &&
- cert->equals(cert, (certificate_t*)value))
- {
- found = TRUE;
- break;
- }
- }
- enumerator->destroy(enumerator);
- return found;
-}
-
-/**
- * build a trustchain from subject up to a trust anchor in trusted
- */
-static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
- certificate_t *subject, auth_cfg_t *auth)
-{
- certificate_t *issuer, *current;
- auth_cfg_t *trustchain;
- int pathlen = 0;
-
- trustchain = auth_cfg_create();
-
- current = auth->get(auth, AUTH_RULE_CA_CERT);
- if (!current)
- {
- /* no trust anchor specified, return this cert only */
- trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
- subject->get_ref(subject));
- return trustchain;
- }
- current = subject->get_ref(subject);
- while (TRUE)
- {
- if (auth_contains_cacert(auth, current))
- {
- trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
- return trustchain;
- }
- if (subject == current)
- {
- trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
- }
- else
- {
- trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
- }
- issuer = get_issuer_cert(this, current, FALSE);
- if (!issuer || issuer->equals(issuer, current) ||
- pathlen > X509_MAX_PATH_LEN)
- {
- DESTROY_IF(issuer);
- break;
- }
- current = issuer;
- pathlen++;
- }
- trustchain->destroy(trustchain);
- return NULL;
-}
-
-/**
- * find a private key of a give certificate
- */
-static private_key_t *get_private_by_cert(private_credential_manager_t *this,
- certificate_t *cert, key_type_t type)
-{
- private_key_t *private = NULL;
- identification_t *keyid;
- chunk_t chunk;
- public_key_t *public;
-
- public = cert->get_public_key(cert);
- if (public)
- {
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
- {
- keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
- private = get_private_by_keyid(this, type, keyid);
- keyid->destroy(keyid);
- }
- public->destroy(public);
- }
- return private;
-}
-
-/**
- * Implementation of credential_manager_t.get_private.
- */
-static private_key_t *get_private(private_credential_manager_t *this,
- key_type_t type, identification_t *id,
- auth_cfg_t *auth)
-{
- enumerator_t *enumerator;
- certificate_t *cert;
- private_key_t *private = NULL;
- auth_cfg_t *trustchain;
-
- /* check if this is a lookup by key ID, and do it if so */
- if (id && id->get_type(id) == ID_KEY_ID)
- {
- private = get_private_by_keyid(this, type, id);
- if (private)
- {
- return private;
- }
- }
-
- /* if a specific certificate is preferred, check for a matching key */
- cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
- if (cert)
- {
- private = get_private_by_cert(this, cert, type);
- if (private)
- {
- trustchain = build_trustchain(this, cert, auth);
- if (trustchain)
- {
- auth->merge(auth, trustchain, FALSE);
- trustchain->destroy(trustchain);
- }
- return private;
- }
- }
-
- /* try to build a trust chain for each certificate found */
- enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
- while (enumerator->enumerate(enumerator, &cert))
- {
- private = get_private_by_cert(this, cert, type);
- if (private)
- {
- trustchain = build_trustchain(this, cert, auth);
- if (trustchain)
- {
- auth->merge(auth, trustchain, FALSE);
- trustchain->destroy(trustchain);
- break;
- }
- private->destroy(private);
- private = NULL;
- }
- }
- enumerator->destroy(enumerator);
-
- /* if no valid trustchain was found, fall back to the first usable cert */
- if (!private)
- {
- enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
- while (enumerator->enumerate(enumerator, &cert))
- {
- private = get_private_by_cert(this, cert, type);
- if (private)
- {
- auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
- break;
- }
- }
- enumerator->destroy(enumerator);
- }
- return private;
-}
-
-/**
- * Implementation of credential_manager_t.flush_cache.
- */
-static void flush_cache(private_credential_manager_t *this,
- certificate_type_t type)
-{
- this->cache->flush(this->cache, type);
-}
-
-/**
- * Implementation of credential_manager_t.add_set.
- */
-static void add_set(private_credential_manager_t *this,
- credential_set_t *set)
-{
- this->lock->write_lock(this->lock);
- this->sets->insert_last(this->sets, set);
- this->lock->unlock(this->lock);
-}
-
-/**
- * Implementation of credential_manager_t.remove_set.
- */
-static void remove_set(private_credential_manager_t *this, credential_set_t *set)
-{
- this->lock->write_lock(this->lock);
- this->sets->remove(this->sets, set, NULL);
- this->lock->unlock(this->lock);
-}
-
-/**
- * Implementation of credential_manager_t.destroy
- */
-static void destroy(private_credential_manager_t *this)
-{
- cache_queue(this);
- this->cache_queue->destroy(this->cache_queue);
- this->sets->remove(this->sets, this->cache, NULL);
- this->sets->destroy(this->sets);
- this->local_sets->destroy(this->local_sets);
- this->cache->destroy(this->cache);
- this->lock->destroy(this->lock);
- this->queue_mutex->destroy(this->queue_mutex);
- free(this);
-}
-
-/*
- * see header file
- */
-credential_manager_t *credential_manager_create()
-{
- private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
-
- this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator;
- this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator;
- this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator;
- this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
- this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
- this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private;
- this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator;
- this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
- this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert;
- this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
- this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
- this->public.destroy = (void(*)(credential_manager_t*))destroy;
-
- this->sets = linked_list_create();
- this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
- this->cache = cert_cache_create();
- this->cache_queue = linked_list_create();
- this->sets->insert_first(this->sets, this->cache);
- this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
- this->queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
-
- return &this->public;
-}
-
diff --git a/src/libcharon/credentials/credential_manager.h b/src/libcharon/credentials/credential_manager.h
deleted file mode 100644
index 0448da992..000000000
--- a/src/libcharon/credentials/credential_manager.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2007-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup credential_manager credential_manager
- * @{ @ingroup ccredentials
- */
-
-#ifndef CREDENTIAL_MANAGER_H_
-#define CREDENTIAL_MANAGER_H_
-
-#include <utils/identification.h>
-#include <utils/enumerator.h>
-#include <config/auth_cfg.h>
-#include <credentials/credential_set.h>
-#include <credentials/keys/private_key.h>
-#include <credentials/keys/shared_key.h>
-#include <credentials/certificates/certificate.h>
-
-typedef struct credential_manager_t credential_manager_t;
-
-/**
- * Manages credentials using credential_sets.
- *
- * The credential manager is the entry point of the credential framework. It
- * uses so called "sets" to access credentials in a modular fashion, these
- * are implemented through the credential_set_t interface.
- * The manager additionally does trust chain verification and trust status
- * chaching. A set may call the managers methods if it needs credentials itself,
- * the manager uses recursive locking.
- *
- * @verbatim
-
- +-------+ +----------------+
- | A | | | +------------------+
- | u | -----> | | ------> | +------------------+
- | t | | credential- | | | +------------------+
- | h | -----> | manager | ------> +--| | credential- | => IPC
- | e | | | +--| sets |
- | n | +--> | | ------> +------------------+
- | t | | | | |
- | i | | | | |
- | c | | +----------------+ |
- | a | | |
- | t | +----------------------------------------------+
- | o | may be recursive
- | r |
- +-------+
-
- @endverbatim
- *
- * The credential manager uses rwlocks for performance reasons, credential
- * sets must be fully thread save.
- */
-struct credential_manager_t {
-
- /**
- * Create an enumerator over all certificates.
- *
- * @param cert kind of certificate
- * @param key kind of key in certificate
- * @param id subject this certificate belongs to
- * @param trusted TRUE to list trusted certificates only
- * @return enumerator over the certificates
- */
- enumerator_t *(*create_cert_enumerator)(credential_manager_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted);
- /**
- * Create an enumerator over all shared keys.
- *
- * The enumerator enumerates over:
- * shared_key_t*, id_match_t me, id_match_t other
- * But must accepts values for the id_matches.
- *
- * @param type kind of requested shared key
- * @param first first subject between key is shared
- * @param second second subject between key is shared
- * @return enumerator over shared keys
- */
- enumerator_t *(*create_shared_enumerator)(credential_manager_t *this,
- shared_key_type_t type,
- identification_t *first, identification_t *second);
- /**
- * Create an enumerator over all Certificate Distribution Points.
- *
- * @param type kind of certificate the point distributes
- * @param id identification of the distributed certificate
- * @return enumerator of CDPs as char*
- */
- enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this,
- certificate_type_t type, identification_t *id);
- /**
- * Get a trusted or untrusted certificate.
- *
- * @param cert kind of certificate
- * @param key kind of key in certificate
- * @param id subject this certificate belongs to
- * @param trusted TRUE to get a trusted certificate only
- * @return certificate, if found, NULL otherwise
- */
- certificate_t *(*get_cert)(credential_manager_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted);
- /**
- * Get the best matching shared key for two IDs.
- *
- * @param type kind of requested shared key
- * @param me own identity
- * @param other peers identity
- * @return shared_key_t, NULL if none found
- */
- shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type,
- identification_t *me, identification_t *other);
- /**
- * Get a private key to create a signature.
- *
- * The get_private() method gets a secret private key identified by either
- * the keyid itself or an id the key belongs to.
- * The auth parameter contains additional information, such as receipients
- * trusted CA certs. Auth gets filled with subject and CA certificates
- * needed to validate a created signature.
- *
- * @param type type of the key to get
- * @param id identification the key belongs to
- * @param auth auth config, including trusted CA certificates
- * @return private_key_t, NULL if none found
- */
- private_key_t* (*get_private)(credential_manager_t *this, key_type_t type,
- identification_t *id, auth_cfg_t *auth);
-
- /**
- * Create an enumerator over trusted public keys.
- *
- * This method gets a an enumerator over trusted public keys to verify a
- * signature created by id. The auth parameter contains additional
- * authentication infos, e.g. peer and intermediate certificates.
- * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *,
- * where the auth config helper contains rules for constraint checks.
- *
- * @param type type of the key to get
- * @param id owner of the key, signer of the signature
- * @param auth authentication infos
- * @return enumerator
- */
- enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
- key_type_t type, identification_t *id, auth_cfg_t *auth);
-
- /**
- * Cache a certificate by invoking cache_cert() on all registerd sets.
- *
- * @param cert certificate to cache
- */
- void (*cache_cert)(credential_manager_t *this, certificate_t *cert);
-
- /**
- * Flush the certificate cache.
- *
- * Only the managers local cache is flushed, but not the sets cache filled
- * by the cache_cert() method.
- *
- * @param type type of certificate to flush, or CERT_ANY
- */
- void (*flush_cache)(credential_manager_t *this, certificate_type_t type);
-
- /**
- * Register a credential set to the manager.
- *
- * @param set set to register
- */
- void (*add_set)(credential_manager_t *this, credential_set_t *set);
-
- /**
- * Unregister a credential set from the manager.
- *
- * @param set set to unregister
- */
- void (*remove_set)(credential_manager_t *this, credential_set_t *set);
-
- /**
- * Destroy a credential_manager instance.
- */
- void (*destroy)(credential_manager_t *this);
-};
-
-/**
- * Create a credential_manager instance.
- */
-credential_manager_t *credential_manager_create();
-
-#endif /** CREDENTIAL_MANAGER_H_ @}*/
diff --git a/src/libcharon/credentials/credential_set.h b/src/libcharon/credentials/credential_set.h
deleted file mode 100644
index 274eb3feb..000000000
--- a/src/libcharon/credentials/credential_set.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2007 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup credential_set credential_set
- * @{ @ingroup ccredentials
- */
-
-#ifndef CREDENTIAL_SET_H_
-#define CREDENTIAL_SET_H_
-
-#include <credentials/keys/public_key.h>
-#include <credentials/keys/shared_key.h>
-#include <credentials/certificates/certificate.h>
-
-typedef struct credential_set_t credential_set_t;
-
-/**
- * A set of credentials.
- *
- * Contains private keys, shared keys and different kinds of certificates.
- * Enumerators are used because queries might return multiple matches.
- * Filter parameters restrict enumeration over specific items only.
- * See credential_manager_t for an overview of the credential framework.
- *
- * A credential set enumerator may not block the credential set, i.e. multiple
- * threads must be able to hold multiple enumerators, as the credential manager
- * is higly parallelized. The best way to achieve this is by using shared
- * read locks for the enumerators only. Otherwiese deadlocks will occur.
- * The writing cache_cert() routine is called by the manager only if no
- * enumerator is alive, so it is save to use a write lock there.
- */
-struct credential_set_t {
-
- /**
- * Create an enumerator over private keys (private_key_t).
- *
- * The id is either a key identifier of the requested key, or an identity
- * of the key owner.
- *
- * @param type type of requested private key
- * @param id key identifier/owner
- * @return enumerator over private_key_t's.
- */
- enumerator_t *(*create_private_enumerator)(credential_set_t *this,
- key_type_t type, identification_t *id);
- /**
- * Create an enumerator over certificates (certificate_t).
- *
- * @param cert kind of certificate
- * @param key kind of key in certificate
- * @param id identity (subject) this certificate belongs to
- * @param trusted whether the certificate must be trustworthy
- * @return enumerator as described above
- */
- enumerator_t *(*create_cert_enumerator)(credential_set_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted);
- /**
- * Create an enumerator over shared keys (shared_key_t).
- *
- * The enumerator enumerates over:
- * shared_key_t*, id_match_t me, id_match_t other
- * But must accept NULL values for the id_matches.
- *
- * @param type kind of requested shared key
- * @param me own identity
- * @param other other identity who owns that secret
- * @return enumerator as described above
- */
- enumerator_t *(*create_shared_enumerator)(credential_set_t *this,
- shared_key_type_t type,
- identification_t *me, identification_t *other);
-
- /**
- * Create an enumerator over certificate distribution points.
- *
- * @param type type of the certificate to get a CDP
- * @param id identification of the distributed certificate
- * @return an enumerator over CDPs as char*
- */
- enumerator_t *(*create_cdp_enumerator)(credential_set_t *this,
- certificate_type_t type, identification_t *id);
-
- /**
- * Cache a certificate in the credential set.
- *
- * The caching policy is implementation dependent, the sets may cache the
- * certificate in-memory, persistent on disk or not at all.
- *
- * @param cert certificate to cache
- */
- void (*cache_cert)(credential_set_t *this, certificate_t *cert);
-};
-
-#endif /** CREDENTIAL_SET_H_ @}*/
diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.c b/src/libcharon/credentials/sets/auth_cfg_wrapper.c
deleted file mode 100644
index 82e33d283..000000000
--- a/src/libcharon/credentials/sets/auth_cfg_wrapper.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Copyright (C) 2008 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <daemon.h>
-
-#include "auth_cfg_wrapper.h"
-
-typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
-
-/**
- * private data of auth_cfg_wrapper
- */
-struct private_auth_cfg_wrapper_t {
-
- /**
- * public functions
- */
- auth_cfg_wrapper_t public;
-
- /**
- * wrapped auth info
- */
- auth_cfg_t *auth;
-};
-
-/**
- * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** inner enumerator from auth_cfg */
- enumerator_t *inner;
- /** wrapped auth round */
- auth_cfg_t *auth;
- /** enumerated cert type */
- certificate_type_t cert;
- /** enumerated key type */
- key_type_t key;
- /** enumerated id */
- identification_t *id;
-} wrapper_enumerator_t;
-
-/**
- * Tries to fetch a certificate that was supplied as "Hash and URL"
- * (replaces rule type and value in place).
- */
-static bool fetch_cert(wrapper_enumerator_t *enumerator,
- auth_rule_t *rule, void **value)
-{
- char *url = (char*)*value;
- if (!url)
- {
- /* fetching the certificate previously failed */
- return FALSE;
- }
-
- chunk_t data;
- certificate_t *cert;
-
- DBG1(DBG_CFG, " fetching certificate from '%s' ...", url);
- if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
- {
- DBG1(DBG_CFG, " fetching certificate failed");
- /* we set the item to NULL, so we can skip it */
- enumerator->auth->replace(enumerator->auth, enumerator->inner,
- *rule, NULL);
- return FALSE;
- }
-
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, data, BUILD_END);
- free(data.ptr);
-
- if (!cert)
- {
- DBG1(DBG_CFG, " parsing fetched certificate failed");
- /* we set the item to NULL, so we can skip it */
- enumerator->auth->replace(enumerator->auth, enumerator->inner,
- *rule, NULL);
- return FALSE;
- }
-
- DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert));
- charon->credentials->cache_cert(charon->credentials, cert);
-
- if (*rule == AUTH_HELPER_IM_HASH_URL)
- {
- *rule = AUTH_HELPER_IM_CERT;
- }
- else
- {
- *rule = AUTH_HELPER_SUBJECT_CERT;
- }
- *value = cert;
- enumerator->auth->replace(enumerator->auth, enumerator->inner,
- *rule, cert->get_ref(cert));
- return TRUE;
-}
-
-/**
- * enumerate function for wrapper_enumerator_t
- */
-static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
-{
- auth_rule_t rule;
- certificate_t *current;
- public_key_t *public;
-
- while (this->inner->enumerate(this->inner, &rule, &current))
- {
- if (rule == AUTH_HELPER_IM_HASH_URL ||
- rule == AUTH_HELPER_SUBJECT_HASH_URL)
- { /* on-demand fetching of hash and url certificates */
- if (!fetch_cert(this, &rule, (void**)&current))
- {
- continue;
- }
- }
- else if (rule != AUTH_HELPER_SUBJECT_CERT &&
- rule != AUTH_HELPER_IM_CERT)
- { /* handle only HELPER certificates */
- continue;
- }
- if (this->cert != CERT_ANY && this->cert != current->get_type(current))
- { /* CERT type requested, but does not match */
- continue;
- }
- public = current->get_public_key(current);
- if (this->key != KEY_ANY && !public)
- { /* key type requested, but no public key */
- DESTROY_IF(public);
- continue;
- }
- if (this->key != KEY_ANY && public && this->key != public->get_type(public))
- { /* key type requested, but public key has another type */
- DESTROY_IF(public);
- continue;
- }
- DESTROY_IF(public);
- if (this->id && !current->has_subject(current, this->id))
- { /* subject requested, but does not match */
- continue;
- }
- *cert = current;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * destroy function for wrapper_enumerator_t
- */
-static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
-{
- this->inner->destroy(this->inner);
- free(this);
-}
-
-/**
- * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
- */
-static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- wrapper_enumerator_t *enumerator;
-
- if (trusted)
- {
- return NULL;
- }
- enumerator = malloc_thing(wrapper_enumerator_t);
- enumerator->auth = this->auth;
- enumerator->cert = cert;
- enumerator->key = key;
- enumerator->id = id;
- enumerator->inner = this->auth->create_enumerator(this->auth);
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
- return &enumerator->public;
-}
-
-/**
- * Implementation of auth_cfg_wrapper_t.destroy
- */
-static void destroy(private_auth_cfg_wrapper_t *this)
-{
- free(this);
-}
-
-/*
- * see header file
- */
-auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
-{
- private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_wrapper_t);
-
- this->public.set.create_private_enumerator = (void*)return_null;
- this->public.set.create_cert_enumerator = (void*)create_enumerator;
- this->public.set.create_shared_enumerator = (void*)return_null;
- this->public.set.create_cdp_enumerator = (void*)return_null;
- this->public.set.cache_cert = (void*)nop;
- this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy;
-
- this->auth = auth;
-
- return &this->public;
-}
-
diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.h b/src/libcharon/credentials/sets/auth_cfg_wrapper.h
deleted file mode 100644
index 7653fcdbf..000000000
--- a/src/libcharon/credentials/sets/auth_cfg_wrapper.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup auth_cfg_wrapper auth_cfg_wrapper
- * @{ @ingroup sets
- */
-
-#ifndef AUTH_CFG_WRAPPER_H_
-#define AUTH_CFG_WRAPPER_H_
-
-#include <config/auth_cfg.h>
-#include <credentials/credential_set.h>
-
-typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
-
-/**
- * A wrapper around auth_cfg_t to handle it as a credential set.
- */
-struct auth_cfg_wrapper_t {
-
- /**
- * implements credential_set_t
- */
- credential_set_t set;
-
- /**
- * Destroy a auth_cfg_wrapper instance.
- */
- void (*destroy)(auth_cfg_wrapper_t *this);
-};
-
-/**
- * Create a auth_cfg_wrapper instance.
- *
- * @param auth the wrapped auth info
- * @return wrapper around auth
- */
-auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
-
-#endif /** AUTH_CFG_WRAPPER_H_ @}*/
diff --git a/src/libcharon/credentials/sets/cert_cache.c b/src/libcharon/credentials/sets/cert_cache.c
deleted file mode 100644
index 176accce2..000000000
--- a/src/libcharon/credentials/sets/cert_cache.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "cert_cache.h"
-
-#include <time.h>
-#include <sched.h>
-
-#include <daemon.h>
-#include <threading/rwlock.h>
-#include <utils/linked_list.h>
-
-/** cache size, a power of 2 for fast modulo */
-#define CACHE_SIZE 32
-
-/** attempts to acquire a cache lock */
-#define REPLACE_TRIES 5
-
-typedef struct private_cert_cache_t private_cert_cache_t;
-typedef struct relation_t relation_t;
-
-/**
- * A trusted relation between subject and issuer
- */
-struct relation_t {
-
- /**
- * subject of this relation
- */
- certificate_t *subject;
-
- /**
- * issuer of this relation
- */
- certificate_t *issuer;
-
- /**
- * Cache hits
- */
- u_int hits;
-
- /**
- * Lock for this relation
- */
- rwlock_t *lock;
-};
-
-/**
- * private data of cert_cache
- */
-struct private_cert_cache_t {
-
- /**
- * public functions
- */
- cert_cache_t public;
-
- /**
- * array of trusted subject-issuer relations
- */
- relation_t relations[CACHE_SIZE];
-};
-
-/**
- * Cache relation in a free slot/replace an other
- */
-static void cache(private_cert_cache_t *this,
- certificate_t *subject, certificate_t *issuer)
-{
- relation_t *rel;
- int i, offset, try;
- u_int total_hits = 0;
-
- /* check for a unused relation slot first */
- for (i = 0; i < CACHE_SIZE; i++)
- {
- rel = &this->relations[i];
-
- if (!rel->subject && rel->lock->try_write_lock(rel->lock))
- {
- /* double-check having lock */
- if (!rel->subject)
- {
- rel->subject = subject->get_ref(subject);
- rel->issuer = issuer->get_ref(issuer);
- return rel->lock->unlock(rel->lock);
- }
- rel->lock->unlock(rel->lock);
- }
- total_hits += rel->hits;
- }
- /* run several attempts to replace a random slot, never block. */
- for (try = 0; try < REPLACE_TRIES; try++)
- {
- /* replace a random relation */
- offset = random();
- for (i = 0; i < CACHE_SIZE; i++)
- {
- rel = &this->relations[(i + offset) % CACHE_SIZE];
-
- if (rel->hits > total_hits / CACHE_SIZE)
- { /* skip often used slots */
- continue;
- }
- if (rel->lock->try_write_lock(rel->lock))
- {
- if (rel->subject)
- {
- rel->subject->destroy(rel->subject);
- rel->issuer->destroy(rel->issuer);
- }
- rel->subject = subject->get_ref(subject);
- rel->issuer = issuer->get_ref(issuer);
- rel->hits = 0;
- return rel->lock->unlock(rel->lock);
- }
- }
- /* give other threads a chance to release locks */
- sched_yield();
- }
-}
-
-/**
- * Implementation of cert_cache_t.issued_by.
- */
-static bool issued_by(private_cert_cache_t *this,
- certificate_t *subject, certificate_t *issuer)
-{
- relation_t *found = NULL, *current;
- int i;
-
- for (i = 0; i < CACHE_SIZE; i++)
- {
- current = &this->relations[i];
-
- current->lock->read_lock(current->lock);
- if (current->subject)
- {
- /* check for equal issuer */
- if (issuer->equals(issuer, current->issuer))
- {
- /* reuse issuer instance in cache() */
- issuer = current->issuer;
- if (subject->equals(subject, current->subject))
- {
- /* write hit counter is not locked, but not critical */
- current->hits++;
- found = current;
- }
- }
- }
- current->lock->unlock(current->lock);
- if (found)
- {
- return TRUE;
- }
- }
- /* no cache hit, check and cache signature */
- if (subject->issued_by(subject, issuer))
- {
- cache(this, subject, issuer);
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * certificate enumerator implemenation
- */
-typedef struct {
- /** implements enumerator_t interface */
- enumerator_t public;
- /** type of requested certificate */
- certificate_type_t cert;
- /** type of requested key */
- key_type_t key;
- /** ID to get a cert for */
- identification_t *id;
- /** cache */
- relation_t *relations;
- /** current position in array cache */
- int index;
- /** currently locked relation */
- int locked;
-} cert_enumerator_t;
-
-/**
- * filter function for certs enumerator
- */
-static bool cert_enumerate(cert_enumerator_t *this, certificate_t **out)
-{
- public_key_t *public;
- relation_t *rel;
-
- if (this->locked >= 0)
- {
- rel = &this->relations[this->locked];
- rel->lock->unlock(rel->lock);
- this->locked = -1;
- }
-
- while (++this->index < CACHE_SIZE)
- {
- rel = &this->relations[this->index];
- rel->lock->read_lock(rel->lock);
- this->locked = this->index;
- if (rel->subject)
- {
- /* CRL lookup is done using issuer/authkeyidentifier */
- if (this->key == KEY_ANY && this->id &&
- (this->cert == CERT_ANY || this->cert == CERT_X509_CRL) &&
- rel->subject->get_type(rel->subject) == CERT_X509_CRL &&
- rel->subject->has_issuer(rel->subject, this->id))
- {
- *out = rel->subject;
- return TRUE;
- }
- if ((this->cert == CERT_ANY ||
- rel->subject->get_type(rel->subject) == this->cert) &&
- (!this->id || rel->subject->has_subject(rel->subject, this->id)))
- {
- if (this->key == KEY_ANY)
- {
- *out = rel->subject;
- return TRUE;
- }
- public = rel->subject->get_public_key(rel->subject);
- if (public)
- {
- if (public->get_type(public) == this->key)
- {
- public->destroy(public);
- *out = rel->subject;
- return TRUE;
- }
- public->destroy(public);
- }
- }
- }
- this->locked = -1;
- rel->lock->unlock(rel->lock);
- }
- return FALSE;
-}
-
-/**
- * clean up enumeration data
- */
-static void cert_enumerator_destroy(cert_enumerator_t *this)
-{
- relation_t *rel;
-
- if (this->locked >= 0)
- {
- rel = &this->relations[this->locked];
- rel->lock->unlock(rel->lock);
- }
- free(this);
-}
-
-/**
- * implementation of credential_set_t.create_cert_enumerator
- */
-static enumerator_t *create_enumerator(private_cert_cache_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- cert_enumerator_t *enumerator;
-
- if (trusted)
- {
- return NULL;
- }
- enumerator = malloc_thing(cert_enumerator_t);
- enumerator->public.enumerate = (void*)cert_enumerate;
- enumerator->public.destroy = (void*)cert_enumerator_destroy;
- enumerator->cert = cert;
- enumerator->key = key;
- enumerator->id = id;
- enumerator->relations = this->relations;
- enumerator->index = -1;
- enumerator->locked = -1;
-
- return &enumerator->public;
-}
-
-/**
- * Implementation of cert_cache_t.flush.
- */
-static void flush(private_cert_cache_t *this, certificate_type_t type)
-{
- relation_t *rel;
- int i;
-
- for (i = 0; i < CACHE_SIZE; i++)
- {
- rel = &this->relations[i];
- if (!rel->subject)
- {
- continue;
- }
- /* check with cheap read lock first */
- if (type != CERT_ANY)
- {
- rel->lock->read_lock(rel->lock);
- if (!rel->subject || type != rel->subject->get_type(rel->subject))
- {
- rel->lock->unlock(rel->lock);
- continue;
- }
- rel->lock->unlock(rel->lock);
- }
- /* double check in write lock */
- rel->lock->write_lock(rel->lock);
- if (rel->subject)
- {
- if (type == CERT_ANY || type == rel->subject->get_type(rel->subject))
- {
- rel->subject->destroy(rel->subject);
- rel->issuer->destroy(rel->issuer);
- rel->subject = NULL;
- rel->issuer = NULL;
- rel->hits = 0;
- }
- }
- rel->lock->unlock(rel->lock);
- }
-}
-
-/**
- * Implementation of cert_cache_t.destroy
- */
-static void destroy(private_cert_cache_t *this)
-{
- relation_t *rel;
- int i;
-
- for (i = 0; i < CACHE_SIZE; i++)
- {
- rel = &this->relations[i];
- if (rel->subject)
- {
- rel->subject->destroy(rel->subject);
- rel->issuer->destroy(rel->issuer);
- }
- rel->lock->destroy(rel->lock);
- }
- free(this);
-}
-
-/*
- * see header file
- */
-cert_cache_t *cert_cache_create()
-{
- private_cert_cache_t *this;
- int i;
-
- this = malloc_thing(private_cert_cache_t);
- this->public.set.create_private_enumerator = (void*)return_null;
- this->public.set.create_cert_enumerator = (void*)create_enumerator;
- this->public.set.create_shared_enumerator = (void*)return_null;
- this->public.set.create_cdp_enumerator = (void*)return_null;
- this->public.set.cache_cert = (void*)nop;
- this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by;
- this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush;
- this->public.destroy = (void(*)(cert_cache_t*))destroy;
-
- for (i = 0; i < CACHE_SIZE; i++)
- {
- this->relations[i].subject = NULL;
- this->relations[i].issuer = NULL;
- this->relations[i].hits = 0;
- this->relations[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
- }
- return &this->public;
-}
-
diff --git a/src/libcharon/credentials/sets/cert_cache.h b/src/libcharon/credentials/sets/cert_cache.h
deleted file mode 100644
index d2721866e..000000000
--- a/src/libcharon/credentials/sets/cert_cache.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup cert_cache cert_cache
- * @{ @ingroup sets
- */
-
-#ifndef CERT_CACHE_H_
-#define CERT_CACHE_H_
-
-#include <credentials/credential_set.h>
-
-typedef struct cert_cache_t cert_cache_t;
-
-/**
- * Certificate signature verification and certificate cache.
- *
- * This cache serves all certificates seen in its issued_by method
- * and serves them as untrusted through the credential set interface. Further,
- * it caches valid subject-issuer relationships to speed up the issued_by
- * method.
- */
-struct cert_cache_t {
-
- /**
- * Implements credential_set_t.
- */
- credential_set_t set;
-
- /**
- * Caching wrapper around certificate_t.issued_by.
- *
- * @param subject certificate to verify
- * @param issuer issuing certificate to verify subject
- * @return TRUE if subject issued by issuer
- */
- bool (*issued_by)(cert_cache_t *this,
- certificate_t *subject, certificate_t *issuer);
-
- /**
- * Flush the certificate cache.
- *
- * @param type type of certificate to flush, or CERT_ANY
- */
- void (*flush)(cert_cache_t *this, certificate_type_t type);
-
- /**
- * Destroy a cert_cache instance.
- */
- void (*destroy)(cert_cache_t *this);
-};
-
-/**
- * Create a cert_cache instance.
- */
-cert_cache_t *cert_cache_create();
-
-#endif /** CERT_CACHE_H_ @}*/
diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.c b/src/libcharon/credentials/sets/ocsp_response_wrapper.c
deleted file mode 100644
index 82079209a..000000000
--- a/src/libcharon/credentials/sets/ocsp_response_wrapper.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "ocsp_response_wrapper.h"
-
-typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t;
-
-/**
- * private data of ocsp_response_wrapper
- */
-struct private_ocsp_response_wrapper_t {
-
- /**
- * public functions
- */
- ocsp_response_wrapper_t public;
-
- /**
- * wrapped OCSP response
- */
- ocsp_response_t *response;
-};
-
-/**
- * enumerator for ocsp_response_wrapper_t.create_cert_enumerator()
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** enumerator over ocsp response */
- enumerator_t *inner;
- /** type of cert */
- certificate_type_t cert;
- /** type of key */
- key_type_t key;
- /** filtering identity */
- identification_t *id;
-} wrapper_enumerator_t;
-
-/**
- * enumerate function wrapper_enumerator_t
- */
-static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
-{
- certificate_t *current;
- public_key_t *public;
-
- while (this->inner->enumerate(this->inner, &current))
- {
- if (this->cert != CERT_ANY && this->cert != current->get_type(current))
- { /* CERT type requested, but does not match */
- continue;
- }
- public = current->get_public_key(current);
- if (this->key != KEY_ANY && !public)
- { /* key type requested, but no public key */
- DESTROY_IF(public);
- continue;
- }
- if (this->key != KEY_ANY && public && this->key != public->get_type(public))
- { /* key type requested, but public key has another type */
- DESTROY_IF(public);
- continue;
- }
- DESTROY_IF(public);
- if (this->id && !current->has_subject(current, this->id))
- { /* subject requested, but does not match */
- continue;
- }
- *cert = current;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * destroy function for wrapper_enumerator_t
- */
-static void enumerator_destroy(wrapper_enumerator_t *this)
-{
- this->inner->destroy(this->inner);
- free(this);
-}
-
-/**
- * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator
- */
-static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this,
- certificate_type_t cert, key_type_t key,
- identification_t *id, bool trusted)
-{
- wrapper_enumerator_t *enumerator;
-
- if (trusted)
- {
- return NULL;
- }
-
- enumerator = malloc_thing(wrapper_enumerator_t);
- enumerator->cert = cert;
- enumerator->key = key;
- enumerator->id = id;
- enumerator->inner = this->response->create_cert_enumerator(this->response);
- enumerator->public.enumerate = (void*)enumerate;
- enumerator->public.destroy = (void*)enumerator_destroy;
- return &enumerator->public;
-}
-
-/**
- * Implementation of ocsp_response_wrapper_t.destroy
- */
-static void destroy(private_ocsp_response_wrapper_t *this)
-{
- free(this);
-}
-
-/*
- * see header file
- */
-ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response)
-{
- private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t);
-
- this->public.set.create_private_enumerator = (void*)return_null;
- this->public.set.create_cert_enumerator = (void*)create_enumerator;
- this->public.set.create_shared_enumerator = (void*)return_null;
- this->public.set.create_cdp_enumerator = (void*)return_null;
- this->public.set.cache_cert = (void*)nop;
- this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy;
-
- this->response = response;
-
- return &this->public;
-}
-
diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.h b/src/libcharon/credentials/sets/ocsp_response_wrapper.h
deleted file mode 100644
index dc4b451df..000000000
--- a/src/libcharon/credentials/sets/ocsp_response_wrapper.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup ocsp_response_wrapper ocsp_response_wrapper
- * @{ @ingroup sets
- */
-
-#ifndef OCSP_RESPONSE_WRAPPER_H_
-#define OCSP_RESPONSE_WRAPPER_H_
-
-#include <credentials/credential_set.h>
-#include <credentials/certificates/ocsp_response.h>
-
-typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t;
-
-/**
- * A wrapper around ocsp_response_t to handle it like a credential set.
- */
-struct ocsp_response_wrapper_t {
-
- /**
- * implements credential_set_t
- */
- credential_set_t set;
-
- /**
- * Destroy a ocsp_response_wrapper instance.
- */
- void (*destroy)(ocsp_response_wrapper_t *this);
-};
-
-/**
- * Create a ocsp_response_wrapper instance.
- *
- * @param response the wrapped OCSP response
- * @return wrapper around response
- */
-ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response);
-
-#endif /** OCSP_RESPONSE_WRAPPER_H_ @}*/
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 11c94beb9..c0227027c 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -19,16 +19,19 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
+#include <syslog.h>
#include <time.h>
#include <errno.h>
+
#ifdef CAPABILITIES
+#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
+#endif /* HAVE_SYS_CAPABILITY_H */
#endif /* CAPABILITIES */
#include "daemon.h"
#include <library.h>
-#include <selectors/traffic_selector.h>
#include <config/proposal.h>
#ifndef LOG_AUTHPRIV /* not defined on OpenSolaris */
@@ -46,12 +49,16 @@ struct private_daemon_t {
*/
daemon_t public;
-#ifdef CAPABILITIES
/**
* capabilities to keep
*/
+#ifdef CAPABILITIES_LIBCAP
cap_t caps;
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ struct __user_cap_data_struct caps;
+#endif /* CAPABILITIES_NATIVE */
+
};
/**
@@ -97,11 +104,12 @@ static void destroy(private_daemon_t *this)
this->public.ike_sa_manager->flush(this->public.ike_sa_manager);
}
DESTROY_IF(this->public.receiver);
+ DESTROY_IF(this->public.sender);
/* unload plugins to release threads */
lib->plugins->unload(lib->plugins);
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
cap_free(this->caps);
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
DESTROY_IF(this->public.traps);
DESTROY_IF(this->public.ike_sa_manager);
DESTROY_IF(this->public.kernel_interface);
@@ -114,8 +122,6 @@ static void destroy(private_daemon_t *this)
DESTROY_IF(this->public.mediation_manager);
#endif /* ME */
DESTROY_IF(this->public.backends);
- DESTROY_IF(this->public.credentials);
- DESTROY_IF(this->public.sender);
DESTROY_IF(this->public.socket);
/* wait until all threads are gone */
DESTROY_IF(this->public.processor);
@@ -133,22 +139,36 @@ static void destroy(private_daemon_t *this)
METHOD(daemon_t, keep_cap, void,
private_daemon_t *this, u_int cap)
{
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET);
cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET);
cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ this->caps.effective |= 1 << cap;
+ this->caps.permitted |= 1 << cap;
+ this->caps.inheritable |= 1 << cap;
+#endif /* CAPABILITIES_NATIVE */
}
METHOD(daemon_t, drop_capabilities, bool,
private_daemon_t *this)
{
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
if (cap_set_proc(this->caps) != 0)
{
return FALSE;
}
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+ struct __user_cap_header_struct header = {
+ .version = _LINUX_CAPABILITY_VERSION,
+ };
+ if (capset(&header, &this->caps) != 0)
+ {
+ return FALSE;
+ }
+#endif /* CAPABILITIES_NATIVE */
return TRUE;
}
@@ -254,8 +274,15 @@ static void initialize_loggers(private_daemon_t *this, bool use_stderr,
filename, strerror(errno));
continue;
}
+ if (lib->settings->get_bool(lib->settings,
+ "charon.filelog.%s.flush_line", FALSE, filename))
+ {
+ setlinebuf(file);
+ }
}
- file_logger = file_logger_create(file);
+ file_logger = file_logger_create(file,
+ lib->settings->get_str(lib->settings,
+ "charon.filelog.%s.time_format", NULL, filename));
def = lib->settings->get_int(lib->settings,
"charon.filelog.%s.default", 1, filename);
for (group = 0; group < DBG_MAX; group++)
@@ -276,7 +303,7 @@ static void initialize_loggers(private_daemon_t *this, bool use_stderr,
if (!loggers_defined)
{
/* set up default stdout file_logger */
- file_logger = file_logger_create(stdout);
+ file_logger = file_logger_create(stdout, NULL);
this->public.bus->add_listener(this->public.bus, &file_logger->listener);
this->public.file_loggers->insert_last(this->public.file_loggers,
file_logger);
@@ -331,7 +358,6 @@ METHOD(daemon_t, initialize, bool,
/* load secrets, ca certificates and crls */
this->public.processor = processor_create();
this->public.scheduler = scheduler_create();
- this->public.credentials = credential_manager_create();
this->public.controller = controller_create();
this->public.eap = eap_manager_create();
this->public.sim = sim_manager_create();
@@ -392,7 +418,9 @@ private_daemon_t *daemon_create()
);
#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
this->caps = cap_init();
+#endif /* CAPABILITIES_LIBCAP */
keep_cap(this, CAP_NET_ADMIN);
if (lib->leak_detective)
{
@@ -423,10 +451,6 @@ bool libcharon_init()
this = daemon_create();
charon = &this->public;
- lib->printf_hook->add_handler(lib->printf_hook, 'R',
- traffic_selector_printf_hook,
- PRINTF_HOOK_ARGTYPE_POINTER,
- PRINTF_HOOK_ARGTYPE_END);
lib->printf_hook->add_handler(lib->printf_hook, 'P',
proposal_printf_hook,
PRINTF_HOOK_ARGTYPE_POINTER,
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index 9b6d97060..38f0256e7 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -31,12 +31,6 @@
* @defgroup control control
* @ingroup libcharon
*
- * @defgroup ccredentials credentials
- * @ingroup libcharon
- *
- * @defgroup sets sets
- * @ingroup ccredentials
- *
* @defgroup encoding encoding
* @ingroup libcharon
*
@@ -156,7 +150,6 @@ typedef struct daemon_t daemon_t;
#include <sa/ike_sa_manager.h>
#include <sa/trap_manager.h>
#include <config/backend_manager.h>
-#include <credentials/credential_manager.h>
#include <sa/authenticators/eap/eap_manager.h>
#include <sa/authenticators/eap/sim_manager.h>
@@ -206,11 +199,6 @@ struct daemon_t {
backend_manager_t *backends;
/**
- * Manager for the credential backends
- */
- credential_manager_t *credentials;
-
- /**
* The Sender-Thread.
*/
sender_t *sender;
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index acfc0fd44..ee49a6686 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -31,6 +31,7 @@
#include <encoding/payloads/payload.h>
#include <encoding/payloads/encryption_payload.h>
#include <encoding/payloads/unknown_payload.h>
+#include <encoding/payloads/cp_payload.h>
/**
* Max number of notify payloads per IKEv2 Message
@@ -975,6 +976,39 @@ static char* get_string(private_message_t *this, char *buf, int len)
pos += written;
len -= written;
}
+ if (payload->get_type(payload) == CONFIGURATION)
+ {
+ cp_payload_t *cp = (cp_payload_t*)payload;
+ enumerator_t *attributes;
+ configuration_attribute_t *attribute;
+ bool first = TRUE;
+
+ attributes = cp->create_attribute_enumerator(cp);
+ while (attributes->enumerate(attributes, &attribute))
+ {
+ written = snprintf(pos, len, "%s%N", first ? "(" : " ",
+ configuration_attribute_type_short_names,
+ attribute->get_type(attribute));
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ first = FALSE;
+ }
+ attributes->destroy(attributes);
+ if (!first)
+ {
+ written = snprintf(pos, len, ")");
+ if (written >= len || written < 0)
+ {
+ return buf;
+ }
+ pos += written;
+ len -= written;
+ }
+ }
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
index 6dd3141f0..80239f654 100644
--- a/src/libcharon/encoding/payloads/cert_payload.c
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -320,7 +320,12 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert)
free(this);
return NULL;
}
- this->data = cert->get_encoding(cert);
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &this->data))
+ {
+ DBG1(DBG_ENC, "encoding certificate for cert payload failed");
+ free(this);
+ return NULL;
+ }
this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len;
return &this->public;
}
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
index 64a43a7fc..837e628bc 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -67,8 +67,8 @@ METHOD(kernel_interface_t, get_cpi, status_t,
METHOD(kernel_interface_t, add_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
- lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ mark_t mark, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts)
{
@@ -77,82 +77,84 @@ METHOD(kernel_interface_t, add_sa, status_t,
return NOT_SUPPORTED;
}
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
- lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi,
- encap, inbound, src_ts, dst_ts);
+ mark, lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp,
+ cpi, encap, inbound, src_ts, dst_ts);
}
METHOD(kernel_interface_t, update_sa, status_t,
private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
- new_src, new_dst, encap, new_encap);
+ new_src, new_dst, encap, new_encap, mark);
}
METHOD(kernel_interface_t, query_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
- return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
+ return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark, bytes);
}
METHOD(kernel_interface_t, del_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int16_t cpi)
+ protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
- return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi);
+ return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
}
METHOD(kernel_interface_t, add_policy, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
- direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
+ direction, spi, protocol, reqid, mark, mode, ipcomp, cpi, routed);
}
METHOD(kernel_interface_t, query_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
- direction, use_time);
+ direction, mark, use_time);
}
METHOD(kernel_interface_t, del_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
- direction, unrouted);
+ direction, mark, unrouted);
}
METHOD(kernel_interface_t, get_source_addr, host_t*,
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
index 4a62e76b8..92d85f9c9 100644
--- a/src/libcharon/kernel/kernel_interface.h
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -90,6 +90,7 @@ struct kernel_interface_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA
+ * @param mark optional mark for this SA
* @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption
@@ -106,7 +107,7 @@ struct kernel_interface_t {
*/
status_t (*add_sa) (kernel_interface_t *this,
host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid,
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key,
@@ -131,6 +132,7 @@ struct kernel_interface_t {
* @param new_dst new destination address
* @param encap current use of UDP encapsulation
* @param new_encap new use of UDP encapsulation
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA
*/
@@ -138,7 +140,7 @@ struct kernel_interface_t {
u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap);
+ bool encap, bool new_encap, mark_t mark);
/**
* Query the number of bytes processed by an SA from the SAD.
@@ -147,11 +149,13 @@ struct kernel_interface_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+ u_int32_t spi, protocol_id_t protocol, mark_t mark,
+ u_int64_t *bytes);
/**
* Delete a previously installed SA from the SAD.
@@ -161,10 +165,12 @@ struct kernel_interface_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ mark_t mark);
/**
* Add a policy to the SPD.
@@ -180,6 +186,7 @@ struct kernel_interface_t {
* @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
+ * @param mark mark for this policy
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp
@@ -192,8 +199,8 @@ struct kernel_interface_t {
traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed);
+ mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed);
/**
* Query the use time of a policy.
@@ -204,13 +211,15 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param[out] use_time the time of this SA's last use
* @return SUCCESS if operation completed
*/
status_t (*query_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t *use_time);
+ policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time);
/**
* Remove a policy from the SPD.
@@ -223,13 +232,14 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction,
+ policy_dir_t direction, mark_t mark,
bool unrouted);
/**
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
index 300464cf6..d09265cc9 100644
--- a/src/libcharon/kernel/kernel_ipsec.h
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -121,6 +121,7 @@ struct kernel_ipsec_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA
+ * @param mark mark for this SA
* @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption
@@ -138,7 +139,7 @@ struct kernel_ipsec_t {
status_t (*add_sa) (kernel_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- lifetime_cfg_t *lifetime,
+ mark_t mark, lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
@@ -162,6 +163,7 @@ struct kernel_ipsec_t {
* @param new_dst new destination address
* @param encap current use of UDP encapsulation
* @param new_encap new use of UDP encapsulation
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA
*/
@@ -169,7 +171,7 @@ struct kernel_ipsec_t {
u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap);
+ bool encap, bool new_encap, mark_t mark);
/**
* Query the number of bytes processed by an SA from the SAD.
@@ -178,11 +180,13 @@ struct kernel_ipsec_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+ u_int32_t spi, protocol_id_t protocol, mark_t mark,
+ u_int64_t *bytes);
/**
* Delete a previusly installed SA from the SAD.
@@ -192,10 +196,12 @@ struct kernel_ipsec_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ mark_t mark);
/**
* Add a policy to the SPD.
@@ -211,6 +217,7 @@ struct kernel_ipsec_t {
* @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
+ * @param mark mark for this policy
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp
@@ -223,8 +230,8 @@ struct kernel_ipsec_t {
traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed);
+ mark_t mark, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool routed);
/**
* Query the use time of a policy.
@@ -236,13 +243,15 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param[out] use_time the monotonic timestamp of this SA's last use
* @return SUCCESS if operation completed
*/
status_t (*query_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t *use_time);
+ policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time);
/**
* Remove a policy from the SPD.
@@ -255,13 +264,14 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction,
+ policy_dir_t direction, mark_t mark,
bool unrouted);
/**
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index df897021a..63a8cab58 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -103,7 +103,22 @@ struct private_receiver_t {
/**
* Delay for receiving incoming packets, to simulate larger RTT
*/
- u_int receive_delay;
+ int receive_delay;
+
+ /**
+ * Specific message type to delay, 0 for any
+ */
+ int receive_delay_type;
+
+ /**
+ * Delay request messages?
+ */
+ bool receive_delay_request;
+
+ /**
+ * Delay response messages?
+ */
+ bool receive_delay_response;
};
/**
@@ -242,7 +257,7 @@ static bool cookie_required(private_receiver_t *this, message_t *message)
/**
* check if peer has to many half open IKE_SAs
*/
-static bool peer_to_aggressive(private_receiver_t *this, message_t *message)
+static bool peer_too_aggressive(private_receiver_t *this, message_t *message)
{
if (charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
message->get_source(message)) >= this->block_threshold)
@@ -259,7 +274,6 @@ static job_requeue_t receive_packets(private_receiver_t *this)
{
packet_t *packet;
message_t *message;
- job_t *job;
/* read in a packet */
if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
@@ -321,7 +335,7 @@ static job_requeue_t receive_packets(private_receiver_t *this)
}
/* check if peer has not too many IKE_SAs half open */
- if (this->block_threshold && peer_to_aggressive(this, message))
+ if (this->block_threshold && peer_too_aggressive(this, message))
{
DBG1(DBG_NET, "ignoring IKE_SA setup from %H, "
"peer too aggressive", message->get_source(message));
@@ -329,16 +343,25 @@ static job_requeue_t receive_packets(private_receiver_t *this)
return JOB_REQUEUE_DIRECT;
}
}
- job = (job_t*)process_message_job_create(message);
if (this->receive_delay)
{
- charon->scheduler->schedule_job_ms(charon->scheduler,
- job, this->receive_delay);
- }
- else
- {
- charon->processor->queue_job(charon->processor, job);
+ if (this->receive_delay_type == 0 ||
+ this->receive_delay_type == message->get_exchange_type(message))
+ {
+ if ((message->get_request(message) && this->receive_delay_request) ||
+ (!message->get_request(message) && this->receive_delay_response))
+ {
+ DBG1(DBG_NET, "using receive delay: %dms",
+ this->receive_delay);
+ charon->scheduler->schedule_job_ms(charon->scheduler,
+ (job_t*)process_message_job_create(message),
+ this->receive_delay);
+ return JOB_REQUEUE_DIRECT;
+ }
+ }
}
+ charon->processor->queue_job(charon->processor,
+ (job_t*)process_message_job_create(message));
return JOB_REQUEUE_DIRECT;
}
@@ -374,6 +397,12 @@ receiver_t *receiver_create()
}
this->receive_delay = lib->settings->get_int(lib->settings,
"charon.receive_delay", 0);
+ this->receive_delay_type = lib->settings->get_int(lib->settings,
+ "charon.receive_delay_type", 0),
+ this->receive_delay_request = lib->settings->get_bool(lib->settings,
+ "charon.receive_delay_request", TRUE),
+ this->receive_delay_response = lib->settings->get_int(lib->settings,
+ "charon.receive_delay_response", TRUE),
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
if (this->hasher == NULL)
diff --git a/src/libcharon/network/sender.c b/src/libcharon/network/sender.c
index c18f1138e..bb6d50605 100644
--- a/src/libcharon/network/sender.c
+++ b/src/libcharon/network/sender.c
@@ -67,6 +67,21 @@ struct private_sender_t {
* Delay for sending outgoing packets, to simulate larger RTT
*/
int send_delay;
+
+ /**
+ * Specific message type to delay, 0 for any
+ */
+ int send_delay_type;
+
+ /**
+ * Delay request messages?
+ */
+ bool send_delay_request;
+
+ /**
+ * Delay response messages?
+ */
+ bool send_delay_response;
};
METHOD(sender_t, send_, void,
@@ -80,7 +95,23 @@ METHOD(sender_t, send_, void,
if (this->send_delay)
{
- usleep(this->send_delay * 1000);
+ message_t *message;
+
+ message = message_create_from_packet(packet->clone(packet));
+ if (message->parse_header(message) == SUCCESS)
+ {
+ if (this->send_delay_type == 0 ||
+ this->send_delay_type == message->get_exchange_type(message))
+ {
+ if ((message->get_request(message) && this->send_delay_request) ||
+ (!message->get_request(message) && this->send_delay_response))
+ {
+ DBG1(DBG_NET, "using send delay: %dms", this->send_delay);
+ usleep(this->send_delay * 1000);
+ }
+ }
+ }
+ message->destroy(message);
}
this->mutex->lock(this->mutex);
@@ -155,7 +186,13 @@ sender_t * sender_create()
.job = callback_job_create((callback_job_cb_t)send_packets,
this, NULL, NULL),
.send_delay = lib->settings->get_int(lib->settings,
- "charon.send_delay", 0),
+ "charon.send_delay", 0),
+ .send_delay_type = lib->settings->get_int(lib->settings,
+ "charon.send_delay_type", 0),
+ .send_delay_request = lib->settings->get_bool(lib->settings,
+ "charon.send_delay_request", TRUE),
+ .send_delay_response = lib->settings->get_int(lib->settings,
+ "charon.send_delay_response", TRUE),
);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am
new file mode 100644
index 000000000..50d0457f8
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-addrblock.la
+else
+plugin_LTLIBRARIES = libstrongswan-addrblock.la
+endif
+
+libstrongswan_addrblock_la_SOURCES = \
+ addrblock_plugin.h addrblock_plugin.c \
+ addrblock_narrow.h addrblock_narrow.c \
+ addrblock_validator.h addrblock_validator.c
+
+libstrongswan_addrblock_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/resolve/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 92ee85539..4cb047929 100644
--- a/src/libcharon/plugins/resolve/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -34,7 +34,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-subdir = src/libcharon/plugins/resolve
+subdir = src/libcharon/plugins/addrblock
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
@@ -73,17 +73,18 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_resolve_la_LIBADD =
-am_libstrongswan_resolve_la_OBJECTS = resolve_plugin.lo \
- resolve_handler.lo
-libstrongswan_resolve_la_OBJECTS = \
- $(am_libstrongswan_resolve_la_OBJECTS)
-libstrongswan_resolve_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libstrongswan_resolve_la_LDFLAGS) $(LDFLAGS) -o $@
-@MONOLITHIC_FALSE@am_libstrongswan_resolve_la_rpath = -rpath \
+libstrongswan_addrblock_la_LIBADD =
+am_libstrongswan_addrblock_la_OBJECTS = addrblock_plugin.lo \
+ addrblock_narrow.lo addrblock_validator.lo
+libstrongswan_addrblock_la_OBJECTS = \
+ $(am_libstrongswan_addrblock_la_OBJECTS)
+libstrongswan_addrblock_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_addrblock_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_addrblock_la_rpath = -rpath \
@MONOLITHIC_FALSE@ $(plugindir)
-@MONOLITHIC_TRUE@am_libstrongswan_resolve_la_rpath =
+@MONOLITHIC_TRUE@am_libstrongswan_addrblock_la_rpath =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@@ -97,8 +98,8 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(libstrongswan_resolve_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_resolve_la_SOURCES)
+SOURCES = $(libstrongswan_addrblock_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_addrblock_la_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -260,16 +261,15 @@ xml_LIBS = @xml_LIBS@
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libcharon
-AM_CFLAGS = -rdynamic \
- -DRESOLV_CONF=\"${resolv_conf}\"
-
-@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-resolve.la
-@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-resolve.la
-libstrongswan_resolve_la_SOURCES = \
- resolve_plugin.h resolve_plugin.c \
- resolve_handler.h resolve_handler.c
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-addrblock.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-addrblock.la
+libstrongswan_addrblock_la_SOURCES = \
+ addrblock_plugin.h addrblock_plugin.c \
+ addrblock_narrow.h addrblock_narrow.c \
+ addrblock_validator.h addrblock_validator.c
-libstrongswan_resolve_la_LDFLAGS = -module -avoid-version
+libstrongswan_addrblock_la_LDFLAGS = -module -avoid-version
all: all-am
.SUFFIXES:
@@ -283,9 +283,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/addrblock/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/libcharon/plugins/resolve/Makefile
+ $(AUTOMAKE) --gnu src/libcharon/plugins/addrblock/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -344,8 +344,8 @@ clean-pluginLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libstrongswan-resolve.la: $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_DEPENDENCIES)
- $(libstrongswan_resolve_la_LINK) $(am_libstrongswan_resolve_la_rpath) $(libstrongswan_resolve_la_OBJECTS) $(libstrongswan_resolve_la_LIBADD) $(LIBS)
+libstrongswan-addrblock.la: $(libstrongswan_addrblock_la_OBJECTS) $(libstrongswan_addrblock_la_DEPENDENCIES)
+ $(libstrongswan_addrblock_la_LINK) $(am_libstrongswan_addrblock_la_rpath) $(libstrongswan_addrblock_la_OBJECTS) $(libstrongswan_addrblock_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -353,8 +353,9 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_narrow.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addrblock_validator.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.c b/src/libcharon/plugins/addrblock/addrblock_narrow.c
new file mode 100644
index 000000000..f85fa78d6
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/addrblock_narrow.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "addrblock_narrow.h"
+
+#include <daemon.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_addrblock_narrow_t private_addrblock_narrow_t;
+
+/**
+ * Private data of an addrblock_narrow_t object.
+ */
+struct private_addrblock_narrow_t {
+
+ /**
+ * Public addrblock_narrow_t interface.
+ */
+ addrblock_narrow_t public;
+};
+
+/**
+ * Check if the negotiated TS list is acceptable by X509 ipAddrBlock constraints
+ */
+static bool check_constraints(ike_sa_t *ike_sa, linked_list_t *list)
+{
+ auth_cfg_t *auth;
+ enumerator_t *auth_enum;
+ certificate_t *cert = NULL;
+
+ auth_enum = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
+ while (auth_enum->enumerate(auth_enum, &auth))
+ {
+ cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
+ if (cert)
+ {
+ break;
+ }
+ }
+ auth_enum->destroy(auth_enum);
+
+ if (cert && cert->get_type(cert) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)cert;
+
+ if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
+ {
+ enumerator_t *enumerator, *block_enum;
+ traffic_selector_t *ts, *block_ts;
+
+ DBG1(DBG_IKE, "checking certificate-based traffic selector "
+ "constraints [RFC 3779]");
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &ts))
+ {
+ bool contained = FALSE;
+
+ block_enum = x509->create_ipAddrBlock_enumerator(x509);
+ while (block_enum->enumerate(block_enum, &block_ts))
+ {
+ if (ts->is_contained_in(ts, block_ts))
+ {
+ DBG1(DBG_IKE, " TS %R is contained in address block"
+ " constraint %R", ts, block_ts);
+ contained = TRUE;
+ break;
+ }
+ }
+ block_enum->destroy(block_enum);
+
+ if (!contained)
+ {
+ DBG1(DBG_IKE, " TS %R is not contained in any"
+ " address block constraint", ts);
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Delete all traffic selectors in a list
+ */
+static void flush_ts_list(linked_list_t *list)
+{
+ traffic_selector_t *ts;
+
+ while (list->remove_last(list, (void**)&ts) == SUCCESS)
+ {
+ ts->destroy(ts);
+ }
+}
+
+METHOD(listener_t, narrow, bool,
+ private_addrblock_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
+{
+ switch (type)
+ {
+ case NARROW_RESPONDER:
+ case NARROW_INITIATOR_POST_AUTH:
+ case NARROW_INITIATOR_POST_NOAUTH:
+ if (!check_constraints(ike_sa, remote))
+ {
+ flush_ts_list(local);
+ flush_ts_list(remote);
+ }
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+METHOD(addrblock_narrow_t, destroy, void,
+ private_addrblock_narrow_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+addrblock_narrow_t *addrblock_narrow_create()
+{
+ private_addrblock_narrow_t *this;
+
+ INIT(this,
+ .public = {
+ .listener.narrow = _narrow,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/addrblock/addrblock_narrow.h b/src/libcharon/plugins/addrblock/addrblock_narrow.h
new file mode 100644
index 000000000..9ab32e671
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/addrblock_narrow.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup addrblock_narrow addrblock_narrow
+ * @{ @ingroup addrblock
+ */
+
+#ifndef ADDRBLOCK_NARROW_H_
+#define ADDRBLOCK_NARROW_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct addrblock_narrow_t addrblock_narrow_t;
+
+/**
+ * Listener that checks traffic selectors against addrblock constraints.
+ */
+struct addrblock_narrow_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a addrblock_narrow_t.
+ */
+ void (*destroy)(addrblock_narrow_t *this);
+};
+
+/**
+ * Create a addrblock_narrow instance.
+ */
+addrblock_narrow_t *addrblock_narrow_create();
+
+#endif /** ADDRBLOCK_NARROW_H_ @}*/
diff --git a/src/libcharon/plugins/addrblock/addrblock_plugin.c b/src/libcharon/plugins/addrblock/addrblock_plugin.c
new file mode 100644
index 000000000..1c407035d
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/addrblock_plugin.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "addrblock_plugin.h"
+
+#include <daemon.h>
+
+#include "addrblock_validator.h"
+#include "addrblock_narrow.h"
+
+typedef struct private_addrblock_plugin_t private_addrblock_plugin_t;
+
+/**
+ * private data of addrblock_plugin
+ */
+struct private_addrblock_plugin_t {
+
+ /**
+ * public functions
+ */
+ addrblock_plugin_t public;
+
+ /**
+ * Validator implementation instance.
+ */
+ addrblock_validator_t *validator;
+
+ /**
+ * Listener to check TS list
+ */
+ addrblock_narrow_t *narrower;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_addrblock_plugin_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->narrower->listener);
+ lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator);
+ this->narrower->destroy(this->narrower);
+ this->validator->destroy(this->validator);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *addrblock_plugin_create()
+{
+ private_addrblock_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .validator = addrblock_validator_create(),
+ .narrower = addrblock_narrow_create(),
+ );
+ lib->credmgr->add_validator(lib->credmgr, &this->validator->validator);
+ charon->bus->add_listener(charon->bus, &this->narrower->listener);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/resolve/resolve_plugin.h b/src/libcharon/plugins/addrblock/addrblock_plugin.h
index 0148b10d7..87bd516f9 100644
--- a/src/libcharon/plugins/resolve/resolve_plugin.h
+++ b/src/libcharon/plugins/addrblock/addrblock_plugin.h
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -14,29 +14,29 @@
*/
/**
- * @defgroup resolve resolve
+ * @defgroup addrblock addrblock
* @ingroup cplugins
*
- * @defgroup resolve_plugin resolve_plugin
- * @{ @ingroup resolve
+ * @defgroup addrblock_plugin addrblock_plugin
+ * @{ @ingroup addrblock
*/
-#ifndef RESOLVE_PLUGIN_H_
-#define RESOLVE_PLUGIN_H_
+#ifndef ADDRBLOCK_PLUGIN_H_
+#define ADDRBLOCK_PLUGIN_H_
#include <plugins/plugin.h>
-typedef struct resolve_plugin_t resolve_plugin_t;
+typedef struct addrblock_plugin_t addrblock_plugin_t;
/**
- * Plugin that writes received DNS servers in a resolv.conf file.
+ * RFC 3779 address block checking.
*/
-struct resolve_plugin_t {
+struct addrblock_plugin_t {
/**
- * implements plugin interface
+ * Implements plugin_t. interface.
*/
plugin_t plugin;
};
-#endif /** RESOLVE_PLUGIN_H_ @}*/
+#endif /** ADDRBLOCK_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.c b/src/libcharon/plugins/addrblock/addrblock_validator.c
new file mode 100644
index 000000000..44ef38d85
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/addrblock_validator.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "addrblock_validator.h"
+
+#include <debug.h>
+#include <credentials/certificates/x509.h>
+#include <selectors/traffic_selector.h>
+
+typedef struct private_addrblock_validator_t private_addrblock_validator_t;
+
+/**
+ * Private data of an addrblock_validator_t object.
+ */
+struct private_addrblock_validator_t {
+
+ /**
+ * Public addrblock_validator_t interface.
+ */
+ addrblock_validator_t public;
+};
+
+/**
+ * Do the addrblock check for two x509 plugins
+ */
+static bool check_addrblock(x509_t *subject, x509_t *issuer)
+{
+ bool subject_const, issuer_const, contained = TRUE;
+ enumerator_t *subject_enumerator, *issuer_enumerator;
+ traffic_selector_t *subject_ts, *issuer_ts;
+
+ subject_const = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS;
+ issuer_const = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS;
+
+ if (!subject_const && !issuer_const)
+ {
+ return TRUE;
+ }
+ if (!subject_const)
+ {
+ DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
+ return FALSE;
+ }
+ if (!issuer_const)
+ {
+ DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension");
+ return FALSE;
+ }
+ subject_enumerator = subject->create_ipAddrBlock_enumerator(subject);
+ while (subject_enumerator->enumerate(subject_enumerator, &subject_ts))
+ {
+ contained = FALSE;
+
+ issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer);
+ while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts))
+ {
+ if (subject_ts->is_contained_in(subject_ts, issuer_ts))
+ {
+ DBG2(DBG_CFG, " subject address block %R is contained in "
+ "issuer address block %R", subject_ts, issuer_ts);
+ contained = TRUE;
+ break;
+ }
+ }
+ issuer_enumerator->destroy(issuer_enumerator);
+ if (!contained)
+ {
+ DBG1(DBG_CFG, "subject address block %R is not contained in any "
+ "issuer address block", subject_ts);
+ break;
+ }
+ }
+ subject_enumerator->destroy(subject_enumerator);
+ return contained;
+}
+
+METHOD(cert_validator_t, validate, bool,
+ private_addrblock_validator_t *this, certificate_t *subject,
+ certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth)
+{
+ if (subject->get_type(subject) == CERT_X509 &&
+ issuer->get_type(issuer) == CERT_X509)
+ {
+ return check_addrblock((x509_t*)subject, (x509_t*)issuer);
+ }
+ return TRUE;
+}
+
+METHOD(addrblock_validator_t, destroy, void,
+ private_addrblock_validator_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+addrblock_validator_t *addrblock_validator_create()
+{
+ private_addrblock_validator_t *this;
+
+ INIT(this,
+ .public = {
+ .validator.validate = _validate,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/addrblock/addrblock_validator.h b/src/libcharon/plugins/addrblock/addrblock_validator.h
new file mode 100644
index 000000000..423f0d41a
--- /dev/null
+++ b/src/libcharon/plugins/addrblock/addrblock_validator.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup addrblock_validator addrblock_validator
+ * @{ @ingroup addrblock
+ */
+
+#ifndef ADDRBLOCK_VALIDATOR_H_
+#define ADDRBLOCK_VALIDATOR_H_
+
+#include <credentials/cert_validator.h>
+
+typedef struct addrblock_validator_t addrblock_validator_t;
+
+/**
+ * RFC 3779 address block X509 certificate validator.
+ */
+struct addrblock_validator_t {
+
+ /**
+ * Implements cert_validator_t interface.
+ */
+ cert_validator_t validator;
+
+ /**
+ * Destroy a addrblock_validator_t.
+ */
+ void (*destroy)(addrblock_validator_t *this);
+};
+
+/**
+ * Create a addrblock_validator instance.
+ */
+addrblock_validator_t *addrblock_validator_create();
+
+#endif /** ADDRBLOCK_VALIDATOR_H_ @}*/
diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am
index e8423589c..b922ef4af 100644
--- a/src/libcharon/plugins/android/Makefile.am
+++ b/src/libcharon/plugins/android/Makefile.am
@@ -12,7 +12,10 @@ endif
libstrongswan_android_la_SOURCES = \
android_plugin.c android_plugin.h \
- android_handler.c android_handler.h
+ android_service.c android_service.h \
+ android_handler.c android_handler.h \
+ android_logger.c android_logger.h \
+ android_creds.c android_creds.h
libstrongswan_android_la_LDFLAGS = -module -avoid-version
libstrongswan_android_la_LIBADD = -lcutils
diff --git a/src/libcharon/plugins/android/Makefile.in b/src/libcharon/plugins/android/Makefile.in
index 9f12a9c75..6e4903ee1 100644
--- a/src/libcharon/plugins/android/Makefile.in
+++ b/src/libcharon/plugins/android/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -75,7 +75,8 @@ am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_android_la_DEPENDENCIES =
am_libstrongswan_android_la_OBJECTS = android_plugin.lo \
- android_handler.lo
+ android_service.lo android_handler.lo android_logger.lo \
+ android_creds.lo
libstrongswan_android_la_OBJECTS = \
$(am_libstrongswan_android_la_OBJECTS)
libstrongswan_android_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -265,7 +266,10 @@ AM_CFLAGS = -rdynamic
@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-android.la
libstrongswan_android_la_SOURCES = \
android_plugin.c android_plugin.h \
- android_handler.c android_handler.h
+ android_service.c android_service.h \
+ android_handler.c android_handler.h \
+ android_logger.c android_logger.h \
+ android_creds.c android_creds.h
libstrongswan_android_la_LDFLAGS = -module -avoid-version
libstrongswan_android_la_LIBADD = -lcutils
@@ -352,8 +356,11 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_creds.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_logger.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/android_service.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c
new file mode 100644
index 000000000..aa7fc6f92
--- /dev/null
+++ b/src/libcharon/plugins/android/android_creds.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <keystore_get.h>
+
+#include "android_creds.h"
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+
+typedef struct private_android_creds_t private_android_creds_t;
+
+/**
+ * Private data of an android_creds_t object
+ */
+struct private_android_creds_t {
+
+ /**
+ * Public interface
+ */
+ android_creds_t public;
+
+ /**
+ * List of trusted certificates, certificate_t*
+ */
+ linked_list_t *certs;
+
+ /**
+ * User name (ID)
+ */
+ identification_t *user;
+
+ /**
+ * User password
+ */
+ char *pass;
+
+ /**
+ * read/write lock
+ */
+ rwlock_t *lock;
+
+};
+
+/**
+ * Certificate enumerator data
+ */
+typedef struct {
+ private_android_creds_t *this;
+ key_type_t key;
+ identification_t *id;
+} cert_data_t;
+
+/**
+ * Filter function for certificates enumerator
+ */
+static bool cert_filter(cert_data_t *data, certificate_t **in,
+ certificate_t **out)
+{
+ certificate_t *cert = *in;
+ public_key_t *public;
+
+ public = cert->get_public_key(cert);
+ if (!public)
+ {
+ return FALSE;
+ }
+ if (data->key != KEY_ANY && public->get_type(public) != data->key)
+ {
+ public->destroy(public);
+ return FALSE;
+ }
+ if (data->id && data->id->get_type(data->id) == ID_KEY_ID &&
+ public->has_fingerprint(public, data->id->get_encoding(data->id)))
+ {
+ public->destroy(public);
+ *out = cert;
+ return TRUE;
+ }
+ public->destroy(public);
+ if (data->id && !cert->has_subject(cert, data->id))
+ {
+ return FALSE;
+ }
+ *out = cert;
+ return TRUE;
+}
+
+/**
+ * Destroy certificate enumerator data
+ */
+static void cert_data_destroy(cert_data_t *this)
+{
+ this->this->lock->unlock(this->this->lock);
+ free(this);
+}
+
+METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
+ private_android_creds_t *this, certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ if (cert == CERT_X509 || cert == CERT_ANY)
+ {
+ cert_data_t *data;
+ this->lock->read_lock(this->lock);
+ INIT(data, .this = this, .id = id, .key = key);
+ return enumerator_create_filter(
+ this->certs->create_enumerator(this->certs),
+ (void*)cert_filter, data, (void*)cert_data_destroy);
+ }
+ return NULL;
+}
+
+/**
+ * Shared key enumerator implementation
+ */
+typedef struct {
+ enumerator_t public;
+ private_android_creds_t *this;
+ shared_key_t *key;
+ bool done;
+} shared_enumerator_t;
+
+METHOD(enumerator_t, shared_enumerate, bool,
+ shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
+ id_match_t *other)
+{
+ if (this->done)
+ {
+ return FALSE;
+ }
+ *key = this->key;
+ *me = ID_MATCH_PERFECT;
+ *other = ID_MATCH_ANY;
+ this->done = TRUE;
+ return TRUE;
+}
+
+METHOD(enumerator_t, shared_destroy, void,
+ shared_enumerator_t *this)
+{
+ this->key->destroy(this->key);
+ this->this->lock->unlock(this->this->lock);
+ free(this);
+}
+
+METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
+ private_android_creds_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ shared_enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+
+ if (!this->user || !this->pass)
+ {
+ this->lock->unlock(this->lock);
+ return NULL;
+ }
+ if (type != SHARED_EAP && type != SHARED_IKE)
+ {
+ this->lock->unlock(this->lock);
+ return NULL;
+ }
+ if (me && !me->equals(me, this->user))
+ {
+ this->lock->unlock(this->lock);
+ return NULL;
+ }
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_shared_enumerate,
+ .destroy = _shared_destroy,
+ },
+ .this = this,
+ .done = FALSE,
+ .key = shared_key_create(type, chunk_clone(chunk_create(this->pass,
+ strlen(this->pass)))),
+ );
+ return &enumerator->public;
+}
+
+METHOD(android_creds_t, add_certificate, bool,
+ private_android_creds_t *this, char *name)
+{
+ certificate_t *cert = NULL;
+ bool status = FALSE;
+ chunk_t chunk;
+#ifdef KEYSTORE_MESSAGE_SIZE
+ /* most current interface, the eclair interface (without key length) is
+ * currently not supported */
+ char value[KEYSTORE_MESSAGE_SIZE];
+ chunk.ptr = value;
+ chunk.len = keystore_get(name, strlen(name), chunk.ptr);
+ if (chunk.len > 0)
+#else
+ /* 1.6 interface, allocates memory */
+ chunk.ptr = keystore_get(name, &chunk.len);
+ if (chunk.ptr)
+#endif /* KEYSTORE_MESSAGE_SIZE */
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_PEM, chunk, BUILD_END);
+ if (cert)
+ {
+ this->lock->write_lock(this->lock);
+ this->certs->insert_last(this->certs, cert);
+ this->lock->unlock(this->lock);
+ status = TRUE;
+ }
+#ifndef KEYSTORE_MESSAGE_SIZE
+ free(chunk.ptr);
+#endif /* KEYSTORE_MESSAGE_SIZE */
+ }
+ return status;
+}
+
+METHOD(android_creds_t, set_username_password, void,
+ private_android_creds_t *this, identification_t *id, char *password)
+{
+ this->lock->write_lock(this->lock);
+ DESTROY_IF(this->user);
+ this->user = id->clone(id);
+ free(this->pass);
+ this->pass = password ? strdup(password) : NULL;
+ this->lock->unlock(this->lock);
+}
+
+METHOD(android_creds_t, clear, void,
+ private_android_creds_t *this)
+{
+ certificate_t *cert;
+ this->lock->write_lock(this->lock);
+ while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
+ {
+ cert->destroy(cert);
+ }
+ DESTROY_IF(this->user);
+ free(this->pass);
+ this->user = NULL;
+ this->pass = NULL;
+ this->lock->unlock(this->lock);
+}
+
+METHOD(android_creds_t, destroy, void,
+ private_android_creds_t *this)
+{
+ clear(this);
+ this->certs->destroy(this->certs);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+android_creds_t *android_creds_create()
+{
+ private_android_creds_t *this;
+
+ INIT(this,
+ .public = {
+ .set = {
+ .create_cert_enumerator = _create_cert_enumerator,
+ .create_shared_enumerator = _create_shared_enumerator,
+ .create_private_enumerator = (void*)return_null,
+ .create_cdp_enumerator = (void*)return_null,
+ .cache_cert = (void*)nop,
+ },
+ .add_certificate = _add_certificate,
+ .set_username_password = _set_username_password,
+ .clear = _clear,
+ .destroy = _destroy,
+ },
+ .certs = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/android/android_creds.h b/src/libcharon/plugins/android/android_creds.h
new file mode 100644
index 000000000..0f7b8e0ea
--- /dev/null
+++ b/src/libcharon/plugins/android/android_creds.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_creds android_creds
+ * @{ @ingroup android
+ */
+
+#ifndef ANDROID_CREDS_H_
+#define ANDROID_CREDS_H_
+
+#include <credentials/credential_set.h>
+
+typedef struct android_creds_t android_creds_t;
+
+/**
+ * Android credentials helper.
+ */
+struct android_creds_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Add a trusted CA certificate from the Android keystore to serve by
+ * this set.
+ *
+ * @param name name/ID of the certificate in the keystore
+ * @return FALSE if the certificate does not exist or is invalid
+ */
+ bool (*add_certificate)(android_creds_t *this, char *name);
+
+ /**
+ * Set the username and password for authentication.
+ *
+ * @param id ID of the user
+ * @param password password to use for authentication
+ */
+ void (*set_username_password)(android_creds_t *this, identification_t *id,
+ char *password);
+
+ /**
+ * Clear the stored credentials.
+ */
+ void (*clear)(android_creds_t *this);
+
+ /**
+ * Destroy a android_creds instance.
+ */
+ void (*destroy)(android_creds_t *this);
+
+};
+
+/**
+ * Create an android_creds instance.
+ */
+android_creds_t *android_creds_create();
+
+#endif /** ANDROID_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
index a475eeaab..ec3ff7a51 100644
--- a/src/libcharon/plugins/android/android_handler.c
+++ b/src/libcharon/plugins/android/android_handler.c
@@ -75,7 +75,7 @@ host_t *get_dns_server(int index)
host_t *dns = NULL;
char key[10], value[PROPERTY_VALUE_MAX];
- if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key))
+ if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key))
{
return NULL;
}
@@ -94,7 +94,7 @@ bool set_dns_server(int index, host_t *dns)
{
char key[10], value[PROPERTY_VALUE_MAX];
- if (snprintf(key, sizeof(key), "net.dns%d", index) >= sizeof(key))
+ if (snprintf(key, sizeof(key), "vpn.dns%d", index) >= sizeof(key))
{
return FALSE;
}
diff --git a/src/libcharon/plugins/android/android_logger.c b/src/libcharon/plugins/android/android_logger.c
new file mode 100644
index 000000000..43c56e656
--- /dev/null
+++ b/src/libcharon/plugins/android/android_logger.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <string.h>
+#include <android/log.h>
+
+#include "android_logger.h"
+
+#include <library.h>
+#include <daemon.h>
+
+typedef struct private_android_logger_t private_android_logger_t;
+
+/**
+ * Private data of an android_logger_t object
+ */
+struct private_android_logger_t {
+
+ /**
+ * Public interface
+ */
+ android_logger_t public;
+
+ /**
+ * logging level
+ */
+ int level;
+
+};
+
+
+METHOD(listener_t, log_, bool,
+ private_android_logger_t *this, debug_t group, level_t level,
+ int thread, ike_sa_t* ike_sa, char *format, va_list args)
+{
+ if (level <= this->level)
+ {
+ char sgroup[16], buffer[8192];
+ char *current = buffer, *next;
+ snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
+ vsnprintf(buffer, sizeof(buffer), format, args);
+ while (current)
+ { /* log each line seperately */
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ __android_log_print(ANDROID_LOG_INFO, "charon", "%.2d[%s] %s\n",
+ thread, sgroup, current);
+ current = next;
+ }
+ }
+ /* always stay registered */
+ return TRUE;
+}
+
+METHOD(android_logger_t, destroy, void,
+ private_android_logger_t *this)
+{
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+android_logger_t *android_logger_create()
+{
+ private_android_logger_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .log = _log_,
+ },
+ .destroy = _destroy,
+ },
+ .level = lib->settings->get_int(lib->settings,
+ "charon.plugins.android.loglevel", 1),
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/resolve/resolve_handler.h b/src/libcharon/plugins/android/android_logger.h
index 77bf9781c..c6fe5aff3 100644
--- a/src/libcharon/plugins/resolve/resolve_handler.h
+++ b/src/libcharon/plugins/android/android_logger.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Martin Willi
+ * Copyright (C) 2010 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,36 +14,39 @@
*/
/**
- * @defgroup resolve_handler resolve_handler
- * @{ @ingroup resolve
+ * @defgroup android_logger android_logger
+ * @{ @ingroup android
*/
-#ifndef RESOLVE_HANDLER_H_
-#define RESOLVE_HANDLER_H_
+#ifndef ANDROID_LOGGER_H_
+#define ANDROID_LOGGER_H_
-#include <attributes/attribute_handler.h>
+#include <bus/bus.h>
-typedef struct resolve_handler_t resolve_handler_t;
+typedef struct android_logger_t android_logger_t;
/**
- * Handle DNS configuration attributes by mangling a resolv.conf file.
+ * Android specific logger.
*/
-struct resolve_handler_t {
+struct android_logger_t {
/**
- * Implements the attribute_handler_t interface
+ * Implements bus_listener_t interface
*/
- attribute_handler_t handler;
+ listener_t listener;
/**
- * Destroy a resolve_handler_t.
+ * Destroy the logger.
*/
- void (*destroy)(resolve_handler_t *this);
+ void (*destroy)(android_logger_t *this);
+
};
/**
- * Create a resolve_handler instance.
+ * Create an Android specific logger instance.
+ *
+ * @return logger instance
*/
-resolve_handler_t *resolve_handler_create();
+android_logger_t *android_logger_create();
-#endif /** RESOLVE_HANDLER_H_ @}*/
+#endif /** ANDROID_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c
index 9a558f53b..e2c8572ef 100644
--- a/src/libcharon/plugins/android/android_plugin.c
+++ b/src/libcharon/plugins/android/android_plugin.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -14,7 +15,10 @@
*/
#include "android_plugin.h"
+#include "android_logger.h"
#include "android_handler.h"
+#include "android_creds.h"
+#include "android_service.h"
#include <hydra.h>
#include <daemon.h>
@@ -32,16 +36,38 @@ struct private_android_plugin_t {
android_plugin_t public;
/**
+ * Android specific logger
+ */
+ android_logger_t *logger;
+
+ /**
* Android specific DNS handler
*/
android_handler_t *handler;
+
+ /**
+ * Android specific credential set
+ */
+ android_creds_t *creds;
+
+ /**
+ * Service that interacts with the Android Settings frontend
+ */
+ android_service_t *service;
+
};
METHOD(plugin_t, destroy, void,
- private_android_plugin_t *this)
+ private_android_plugin_t *this)
{
- hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+ hydra->attributes->remove_handler(hydra->attributes,
+ &this->handler->handler);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+ charon->bus->remove_listener(charon->bus, &this->logger->listener);
+ this->creds->destroy(this->creds);
this->handler->destroy(this->handler);
+ this->logger->destroy(this->logger);
+ DESTROY_IF(this->service);
free(this);
}
@@ -56,11 +82,22 @@ plugin_t *android_plugin_create()
.public.plugin = {
.destroy = _destroy,
},
+ .logger = android_logger_create(),
.handler = android_handler_create(),
+ .creds = android_creds_create(),
);
+ charon->bus->add_listener(charon->bus, &this->logger->listener);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+ this->service = android_service_create(this->creds);
+ if (!this->service)
+ {
+ destroy(this);
+ return NULL;
+ }
+
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
new file mode 100644
index 000000000..538c4a9a2
--- /dev/null
+++ b/src/libcharon/plugins/android/android_service.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <unistd.h>
+#include <cutils/sockets.h>
+#include <cutils/properties.h>
+#include <signal.h>
+
+#include "android_service.h"
+
+#include <daemon.h>
+#include <threading/thread.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_android_service_t private_android_service_t;
+
+/**
+ * private data of Android service
+ */
+struct private_android_service_t {
+
+ /**
+ * public interface
+ */
+ android_service_t public;
+
+ /**
+ * current IKE_SA
+ */
+ ike_sa_t *ike_sa;
+
+ /**
+ * job that handles requests from the Android control socket
+ */
+ callback_job_t *job;
+
+ /**
+ * android credentials
+ */
+ android_creds_t *creds;
+
+ /**
+ * android control socket
+ */
+ int control;
+
+};
+
+/**
+ * Some of the error codes defined in VpnManager.java
+ */
+typedef enum {
+ /** Error code to indicate an error from authentication. */
+ VPN_ERROR_AUTH = 51,
+ /** Error code to indicate the connection attempt failed. */
+ VPN_ERROR_CONNECTION_FAILED = 101,
+ /** Error code to indicate an error of remote server hanging up. */
+ VPN_ERROR_REMOTE_HUNG_UP = 7,
+ /** Error code to indicate an error of losing connectivity. */
+ VPN_ERROR_CONNECTION_LOST = 103,
+} android_vpn_errors_t;
+
+/**
+ * send a status code back to the Android app
+ */
+static void send_status(private_android_service_t *this, u_char code)
+{
+ DBG1(DBG_CFG, "status of Android plugin changed: %d", code);
+ send(this->control, &code, 1, 0);
+}
+
+METHOD(listener_t, ike_updown, bool,
+ private_android_service_t *this, ike_sa_t *ike_sa, bool up)
+{
+ /* this callback is only registered during initiation, so if the IKE_SA
+ * goes down we assume an authentication error */
+ if (this->ike_sa == ike_sa && !up)
+ {
+ send_status(this, VPN_ERROR_AUTH);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(listener_t, child_state_change, bool,
+ private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ child_sa_state_t state)
+{
+ /* this callback is only registered during initiation, so we still have
+ * the control socket open */
+ if (this->ike_sa == ike_sa && state == CHILD_DESTROYING)
+ {
+ send_status(this, VPN_ERROR_CONNECTION_FAILED);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Callback used to shutdown the daemon
+ */
+static job_requeue_t shutdown_callback(void *data)
+{
+ kill(0, SIGTERM);
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(listener_t, child_updown, bool,
+ private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ bool up)
+{
+ if (this->ike_sa == ike_sa)
+ {
+ if (up)
+ {
+ /* disable the hooks registered to catch initiation failures */
+ this->public.listener.ike_updown = NULL;
+ this->public.listener.child_state_change = NULL;
+ property_set("vpn.status", "ok");
+ }
+ else
+ {
+ callback_job_t *job;
+ /* the control socket is closed as soon as vpn.status is set to "ok"
+ * and the daemon proxy then only checks for terminated daemons to
+ * detect lost connections, so... */
+ DBG1(DBG_CFG, "connection lost, raising delayed SIGTERM");
+ /* to avoid any conflicts we send the SIGTERM not directly from this
+ * callback, but from a different thread. we also delay it to avoid
+ * a race condition during a regular shutdown */
+ job = callback_job_create(shutdown_callback, NULL, NULL, NULL);
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, 1);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+METHOD(listener_t, ike_rekey, bool,
+ private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ if (this->ike_sa == old)
+ {
+ this->ike_sa = new;
+ }
+ return TRUE;
+}
+
+/**
+ * Read a string argument from the Android control socket
+ */
+static char *read_argument(int fd, u_char length)
+{
+ int offset = 0;
+ char *data = malloc(length + 1);
+ while (offset < length)
+ {
+ int n = recv(fd, &data[offset], length - offset, 0);
+ if (n < 0)
+ {
+ DBG1(DBG_CFG, "failed to read argument from Android"
+ " control socket: %s", strerror(errno));
+ free(data);
+ return NULL;
+ }
+ offset += n;
+ }
+ data[length] = '\0';
+ DBG3(DBG_CFG, "received argument from Android control socket: %s", data);
+ return data;
+}
+
+/**
+ * handle the request received from the Android control socket
+ */
+static job_requeue_t initiate(private_android_service_t *this)
+{
+ bool oldstate;
+ int fd, i = 0;
+ char *hostname = NULL, *cacert = NULL, *username = NULL, *password = NULL;
+ identification_t *gateway = NULL, *user = NULL;
+ ike_cfg_t *ike_cfg;
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *child_cfg;
+ traffic_selector_t *ts;
+ ike_sa_t *ike_sa;
+ auth_cfg_t *auth;
+ lifetime_cfg_t lifetime = {
+ .time = {
+ .life = 10800, /* 3h */
+ .rekey = 10200, /* 2h50min */
+ .jitter = 300 /* 5min */
+ }
+ };
+
+ fd = accept(this->control, NULL, 0);
+ if (fd < 0)
+ {
+ DBG1(DBG_CFG, "accept on Android control socket failed: %s",
+ strerror(errno));
+ return JOB_REQUEUE_NONE;
+ }
+ /* the original control socket is not used anymore */
+ close(this->control);
+ this->control = fd;
+
+ while (TRUE)
+ {
+ u_char length;
+ if (recv(fd, &length, 1, 0) != 1)
+ {
+ DBG1(DBG_CFG, "failed to read from Android control socket: %s",
+ strerror(errno));
+ return JOB_REQUEUE_NONE;
+ }
+
+ if (length == 0xFF)
+ { /* last argument */
+ break;
+ }
+ else
+ {
+ switch (i++)
+ {
+ case 0: /* gateway */
+ hostname = read_argument(fd, length);
+ break;
+ case 1: /* CA certificate name */
+ cacert = read_argument(fd, length);
+ break;
+ case 2: /* username */
+ username = read_argument(fd, length);
+ break;
+ case 3: /* password */
+ password = read_argument(fd, length);
+ break;
+ }
+ }
+ }
+
+ if (cacert)
+ {
+ if (!this->creds->add_certificate(this->creds, cacert))
+ {
+ DBG1(DBG_CFG, "failed to load CA certificate");
+ }
+ /* if this is a server cert we could use the cert subject as id
+ * but we have to test first if that possible to configure */
+ }
+
+ gateway = identification_create_from_string(hostname);
+ DBG1(DBG_CFG, "using CA certificate, gateway identitiy '%Y'", gateway);
+
+ if (username)
+ {
+ user = identification_create_from_string(username);
+ this->creds->set_username_password(this->creds, user, password);
+ }
+
+ ike_cfg = ike_cfg_create(TRUE, FALSE, "0.0.0.0", IKEV2_UDP_PORT,
+ hostname, IKEV2_UDP_PORT);
+ ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+
+ peer_cfg = peer_cfg_create("android", 2, ike_cfg, CERT_SEND_IF_ASKED,
+ UNIQUE_REPLACE, 1, /* keyingtries */
+ 36000, 0, /* rekey 10h, reauth none */
+ 600, 600, /* jitter, over 10min */
+ TRUE, 0, /* mobike, DPD */
+ host_create_from_string("0.0.0.0", 0) /* virt */,
+ NULL, FALSE, NULL, NULL); /* pool, mediation */
+
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+ auth->add(auth, AUTH_RULE_IDENTITY, user);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+ auth->add(auth, AUTH_RULE_IDENTITY, gateway);
+ peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
+
+ child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
+ child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+ ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
+ 0, "255.255.255.255", 65535);
+ child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
+ peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+ /* get an additional reference because initiate consumes one */
+ child_cfg->get_ref(child_cfg);
+
+ /* get us an IKE_SA */
+ ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
+ peer_cfg);
+ if (!ike_sa->get_peer_cfg(ike_sa))
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ }
+ peer_cfg->destroy(peer_cfg);
+
+ /* store the IKE_SA so we can track its progress */
+ this->ike_sa = ike_sa;
+
+ /* confirm that we received the request */
+ send_status(this, i);
+
+ if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "failed to initiate tunnel");
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ send_status(this, VPN_ERROR_CONNECTION_FAILED);
+ return JOB_REQUEUE_NONE;
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(android_service_t, destroy, void,
+ private_android_service_t *this)
+{
+ charon->bus->remove_listener(charon->bus, &this->public.listener);
+ close(this->control);
+ free(this);
+}
+
+/**
+ * See header
+ */
+android_service_t *android_service_create(android_creds_t *creds)
+{
+ private_android_service_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .ike_updown = _ike_updown,
+ .child_state_change = _child_state_change,
+ .child_updown = _child_updown,
+ .ike_rekey = _ike_rekey,
+ },
+ .destroy = _destroy,
+ },
+ .creds = creds,
+ );
+
+ this->control = android_get_control_socket("charon");
+ if (this->control == -1)
+ {
+ DBG1(DBG_CFG, "failed to get Android control socket");
+ free(this);
+ return NULL;
+ }
+
+ if (listen(this->control, 1) < 0)
+ {
+ DBG1(DBG_CFG, "failed to listen on Android control socket: %s",
+ strerror(errno));
+ close(this->control);
+ free(this);
+ return NULL;
+ }
+
+ charon->bus->add_listener(charon->bus, &this->public.listener);
+ this->job = callback_job_create((callback_job_cb_t)initiate, this,
+ NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+
diff --git a/src/libcharon/plugins/android/android_service.h b/src/libcharon/plugins/android/android_service.h
new file mode 100644
index 000000000..d096d6cd5
--- /dev/null
+++ b/src/libcharon/plugins/android/android_service.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_service android_service
+ * @{ @ingroup android
+ */
+
+#ifndef ANDROID_SERVICE_H_
+#define ANDROID_SERVICE_H_
+
+typedef struct android_service_t android_service_t;
+
+#include <bus/listeners/listener.h>
+
+#include "android_creds.h"
+
+/**
+ * Service that interacts with the Android Settings frontend.
+ */
+struct android_service_t {
+
+ /**
+ * Implements listener_t.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy a android_service_t.
+ */
+ void (*destroy)(android_service_t *this);
+
+};
+
+/**
+ * Create an Android service instance.
+ *
+ * @param creds Android credentials
+ */
+android_service_t *android_service_create(android_creds_t *creds);
+
+#endif /** ANDROID_SERVICE_H_ @}*/
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 7606b963c..b34654fb7 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index dbcceb6ce..a6a887780 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -129,7 +129,8 @@ METHOD(attribute_provider_t, release_address, bool,
}
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
- private_dhcp_provider_t *this, identification_t *id, host_t *vip)
+ private_dhcp_provider_t *this, char *pool, identification_t *id,
+ host_t *vip)
{
dhcp_transaction_t *transaction;
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 1cea81a9b..14bf3f15d 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_peer.c b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
index 26546809d..dfcc69710 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_peer.c
+++ b/src/libcharon/plugins/eap_aka/eap_aka_peer.c
@@ -421,7 +421,6 @@ static status_t process_notification(private_eap_aka_peer_t *this,
/* test success bit */
if (!(data.ptr[0] & 0x80))
{
- success = FALSE;
DBG1(DBG_IKE, "received EAP-AKA notification error '%N'",
simaka_notification_names, code);
}
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index d0b0f5601..b41b59616 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
index 9817fff8f..a9767ad91 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
@@ -52,8 +52,7 @@ bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN])
shared_key_t *shared;
chunk_t key;
- shared = charon->credentials->get_shared(charon->credentials,
- SHARED_EAP, id, NULL);
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL);
if (shared == NULL)
{
return FALSE;
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 110e1528b..57952f621 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
index c7f55fa70..f641ad13a 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -168,8 +168,8 @@ static status_t process_peer(private_eap_gtc_t *this,
chunk_t key;
size_t len;
- shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP,
- this->peer, this->server);
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
+ this->peer, this->server);
if (shared == NULL)
{
DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index bbb987dd6..d78957438 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 943811604..5bfc59fa4 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
index 0eda8f755..3554ae12e 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.c
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -85,8 +85,7 @@ static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response,
chunk_t concat;
hasher_t *hasher;
- shared = charon->credentials->get_shared(charon->credentials, SHARED_EAP,
- me, other);
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other);
if (shared == NULL)
{
DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'", me, other);
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 2f6c65df4..d61cc9e5d 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
index c1ccf72eb..3cd8d994c 100644
--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -614,8 +614,7 @@ static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me,
chunk_t password;
/* try to find a stored NT_HASH first */
- shared = charon->credentials->get_shared(charon->credentials,
- SHARED_NT_HASH, me, other);
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_NT_HASH, me, other);
if (shared )
{
*nt_hash = chunk_clone(shared->get_key(shared));
@@ -624,8 +623,7 @@ static bool get_nt_hash(private_eap_mschapv2_t *this, identification_t *me,
}
/* fallback to plaintext password */
- shared = charon->credentials->get_shared(charon->credentials,
- SHARED_EAP, me, other);
+ shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other);
if (shared)
{
password = ascii_to_unicode(shared->get_key(shared));
@@ -820,7 +818,7 @@ static status_t process_peer_failure(private_eap_mschapv2_t *this,
eap_mschapv2_header_t *eap;
chunk_t data;
char *message, *token, *msg = NULL;
- int message_len, error, retryable;
+ int message_len, error = 0, retryable;
chunk_t challenge = chunk_empty;
data = in->get_data(in);
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am
index a3abd4124..afc50bced 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.am
+++ b/src/libcharon/plugins/eap_radius/Makefile.am
@@ -13,6 +13,8 @@ endif
libstrongswan_eap_radius_la_SOURCES = \
eap_radius_plugin.h eap_radius_plugin.c \
eap_radius.h eap_radius.c \
+ radius_server.h radius_server.c \
+ radius_socket.h radius_socket.c \
radius_client.h radius_client.c \
radius_message.h radius_message.c
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index 18427adef..bb372d13c 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -75,7 +75,8 @@ am__installdirs = "$(DESTDIR)$(plugindir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_eap_radius_la_LIBADD =
am_libstrongswan_eap_radius_la_OBJECTS = eap_radius_plugin.lo \
- eap_radius.lo radius_client.lo radius_message.lo
+ eap_radius.lo radius_server.lo radius_socket.lo \
+ radius_client.lo radius_message.lo
libstrongswan_eap_radius_la_OBJECTS = \
$(am_libstrongswan_eap_radius_la_OBJECTS)
libstrongswan_eap_radius_la_LINK = $(LIBTOOL) --tag=CC \
@@ -267,6 +268,8 @@ AM_CFLAGS = -rdynamic
libstrongswan_eap_radius_la_SOURCES = \
eap_radius_plugin.h eap_radius_plugin.c \
eap_radius.h eap_radius.c \
+ radius_server.h radius_server.c \
+ radius_socket.h radius_socket.c \
radius_client.h radius_client.c \
radius_message.h radius_message.c
@@ -358,6 +361,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_radius_plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_client.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_message.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radius_socket.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index f041fda54..65b868bc6 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -53,11 +53,6 @@ struct private_eap_radius_t {
u_int32_t vendor;
/**
- * EAP MSK, if method established one
- */
- chunk_t msk;
-
- /**
* RADIUS client instance
*/
radius_client_t *client;
@@ -71,6 +66,11 @@ struct private_eap_radius_t {
* Prefix to prepend to EAP identity
*/
char *id_prefix;
+
+ /**
+ * Handle the Class attribute as group membership information?
+ */
+ bool class_group;
};
/**
@@ -140,10 +140,8 @@ static bool radius2ike(private_eap_radius_t *this,
return FALSE;
}
-/**
- * Implementation of eap_method_t.initiate
- */
-static status_t initiate(private_eap_radius_t *this, eap_payload_t **out)
+METHOD(eap_method_t, initiate, status_t,
+ private_eap_radius_t *this, eap_payload_t **out)
{
radius_message_t *request, *response;
status_t status = FAILED;
@@ -177,10 +175,44 @@ static status_t initiate(private_eap_radius_t *this, eap_payload_t **out)
}
/**
- * Implementation of eap_method_t.process
+ * Handle the Class attribute as group membership information
*/
-static status_t process(private_eap_radius_t *this,
- eap_payload_t *in, eap_payload_t **out)
+static void process_class(private_eap_radius_t *this, radius_message_t *msg)
+{
+ enumerator_t *enumerator;
+ chunk_t data;
+ int type;
+
+ enumerator = msg->create_enumerator(msg);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_CLASS)
+ {
+ identification_t *id;
+ ike_sa_t *ike_sa;
+ auth_cfg_t *auth;
+
+ if (data.len >= 44)
+ { /* quirk: ignore long class attributes, these are used for
+ * other purposes by some RADIUS servers (such as NPS). */
+ continue;
+ }
+
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa)
+ {
+ auth = ike_sa->get_auth_cfg(ike_sa, FALSE);
+ id = identification_create_from_data(data);
+ DBG1(DBG_CFG, "received group membership '%Y' from RADIUS", id);
+ auth->add(auth, AUTH_RULE_GROUP, id);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(eap_method_t, process, status_t,
+ private_eap_radius_t *this, eap_payload_t *in, eap_payload_t **out)
{
radius_message_t *request, *response;
status_t status = FAILED;
@@ -211,8 +243,10 @@ static status_t process(private_eap_radius_t *this,
status = FAILED;
break;
case RMC_ACCESS_ACCEPT:
- this->msk = this->client->decrypt_msk(this->client,
- response, request);
+ if (this->class_group)
+ {
+ process_class(this, response);
+ }
status = SUCCESS;
break;
case RMC_ACCESS_REJECT:
@@ -228,32 +262,29 @@ static status_t process(private_eap_radius_t *this,
return status;
}
-/**
- * Implementation of eap_method_t.get_type.
- */
-static eap_type_t get_type(private_eap_radius_t *this, u_int32_t *vendor)
+METHOD(eap_method_t, get_type, eap_type_t,
+ private_eap_radius_t *this, u_int32_t *vendor)
{
*vendor = this->vendor;
return this->type;
}
-/**
- * Implementation of eap_method_t.get_msk.
- */
-static status_t get_msk(private_eap_radius_t *this, chunk_t *msk)
+METHOD(eap_method_t, get_msk, status_t,
+ private_eap_radius_t *this, chunk_t *out)
{
- if (this->msk.ptr)
+ chunk_t msk;
+
+ msk = this->client->get_msk(this->client);
+ if (msk.len)
{
- *msk = this->msk;
+ *out = msk;
return SUCCESS;
}
return FAILED;
}
-/**
- * Implementation of eap_method_t.is_mutual.
- */
-static bool is_mutual(private_eap_radius_t *this)
+METHOD(eap_method_t, is_mutual, bool,
+ private_eap_radius_t *this)
{
switch (this->type)
{
@@ -265,15 +296,12 @@ static bool is_mutual(private_eap_radius_t *this)
}
}
-/**
- * Implementation of eap_method_t.destroy.
- */
-static void destroy(private_eap_radius_t *this)
+METHOD(eap_method_t, destroy, void,
+ private_eap_radius_t *this)
{
this->peer->destroy(this->peer);
this->server->destroy(this->server);
this->client->destroy(this->client);
- chunk_clear(&this->msk);
free(this);
}
@@ -282,15 +310,26 @@ static void destroy(private_eap_radius_t *this)
*/
eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer)
{
- private_eap_radius_t *this = malloc_thing(private_eap_radius_t);
-
- this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate;
- this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process;
- this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
- this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
- this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
- this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
-
+ private_eap_radius_t *this;
+
+ INIT(this,
+ .public.eap_method_interface = {
+ .initiate = _initiate,
+ .process = _process,
+ .get_type = _get_type,
+ .is_mutual = _is_mutual,
+ .get_msk = _get_msk,
+ .destroy = _destroy,
+ },
+ /* initially EAP_RADIUS, but is set to the method selected by RADIUS */
+ .type = EAP_RADIUS,
+ .eap_start = lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-radius.eap_start", FALSE),
+ .id_prefix = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.id_prefix", ""),
+ .class_group = lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-radius.class_group", FALSE),
+ );
this->client = radius_client_create();
if (!this->client)
{
@@ -299,14 +338,6 @@ eap_radius_t *eap_radius_create(identification_t *server, identification_t *peer
}
this->peer = peer->clone(peer);
this->server = server->clone(server);
- /* initially EAP_RADIUS, but is set to the method selected by RADIUS */
- this->type = EAP_RADIUS;
- this->vendor = 0;
- this->msk = chunk_empty;
- this->eap_start = lib->settings->get_bool(lib->settings,
- "charon.plugins.eap-radius.eap_start", FALSE);
- this->id_prefix = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.id_prefix", "");
return &this->public;
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
index 7d2788c3e..91aae2f62 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
@@ -17,17 +17,130 @@
#include "eap_radius.h"
#include "radius_client.h"
+#include "radius_server.h"
#include <daemon.h>
/**
- * Implementation of plugin_t.destroy
+ * Default RADIUS server port, when not configured
*/
-static void destroy(eap_radius_plugin_t *this)
+#define RADIUS_PORT 1812
+
+typedef struct private_eap_radius_plugin_t private_eap_radius_plugin_t;
+
+/**
+ * Private data of an eap_radius_plugin_t object.
+ */
+struct private_eap_radius_plugin_t {
+
+ /**
+ * Public radius_plugin_t interface.
+ */
+ eap_radius_plugin_t public;
+
+ /**
+ * List of RADIUS servers
+ */
+ linked_list_t *servers;
+};
+
+/**
+ * Instance of the EAP plugin
+ */
+static private_eap_radius_plugin_t *instance = NULL;
+
+METHOD(plugin_t, destroy, void,
+ private_eap_radius_plugin_t *this)
{
charon->eap->remove_method(charon->eap, (eap_constructor_t)eap_radius_create);
- radius_client_cleanup();
+ this->servers->destroy_offset(this->servers,
+ offsetof(radius_server_t, destroy));
free(this);
+ instance = NULL;
+}
+
+/**
+ * Load RADIUS servers from configuration
+ */
+static bool load_servers(private_eap_radius_plugin_t *this)
+{
+ enumerator_t *enumerator;
+ radius_server_t *server;
+ char *nas_identifier, *secret, *address, *section;
+ int port, sockets, preference;
+
+ address = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.server", NULL);
+ if (address)
+ { /* legacy configuration */
+ secret = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.secret", NULL);
+ if (!secret)
+ {
+ DBG1(DBG_CFG, "no RADUIS secret defined");
+ return FALSE;
+ }
+ nas_identifier = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.nas_identifier", "strongSwan");
+ port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.port", RADIUS_PORT);
+ sockets = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.sockets", 1);
+ server = radius_server_create(address, port, nas_identifier,
+ secret, sockets, 0);
+ if (!server)
+ {
+ DBG1(DBG_CFG, "no RADUIS server defined");
+ return FALSE;
+ }
+ this->servers->insert_last(this->servers, server);
+ return TRUE;
+ }
+
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "charon.plugins.eap-radius.servers");
+ while (enumerator->enumerate(enumerator, &section))
+ {
+ address = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.address", NULL, section);
+ if (!address)
+ {
+ DBG1(DBG_CFG, "RADIUS server '%s' misses address, skipped", section);
+ continue;
+ }
+ secret = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.secret", NULL, section);
+ if (!secret)
+ {
+ DBG1(DBG_CFG, "RADIUS server '%s' misses secret, skipped", section);
+ continue;
+ }
+ nas_identifier = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.nas_identifier",
+ "strongSwan", section);
+ port = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.port", RADIUS_PORT, section);
+ sockets = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.sockets", 1, section);
+ preference = lib->settings->get_int(lib->settings,
+ "charon.plugins.eap-radius.servers.%s.preference", 0, section);
+ server = radius_server_create(address, port, nas_identifier,
+ secret, sockets, preference);
+ if (!server)
+ {
+ DBG1(DBG_CFG, "loading RADIUS server '%s' failed, skipped", section);
+ continue;
+ }
+ this->servers->insert_last(this->servers, server);
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->servers->get_count(this->servers) == 0)
+ {
+ DBG1(DBG_CFG, "no valid RADIUS server configuration found");
+ return FALSE;
+ }
+ return TRUE;
}
/*
@@ -35,20 +148,35 @@ static void destroy(eap_radius_plugin_t *this)
*/
plugin_t *eap_radius_plugin_create()
{
- eap_radius_plugin_t *this;
+ private_eap_radius_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .servers = linked_list_create(),
+ );
- if (!radius_client_init())
+ if (!load_servers(this))
{
- DBG1(DBG_CFG, "RADIUS plugin initialization failed");
+ destroy(this);
return NULL;
}
-
- this = malloc_thing(eap_radius_plugin_t);
- this->plugin.destroy = (void(*)(plugin_t*))destroy;
-
charon->eap->add_method(charon->eap, EAP_RADIUS, 0,
EAP_SERVER, (eap_constructor_t)eap_radius_create);
- return &this->plugin;
+ instance = this;
+
+ return &this->public.plugin;
+}
+
+/**
+ * See header
+ */
+enumerator_t *eap_radius_create_server_enumerator()
+{
+ if (instance)
+ {
+ return instance->servers->create_enumerator(instance->servers);
+ }
+ return enumerator_create_empty();
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h
index f2b8b5082..cb724364a 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.h
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.h
@@ -25,6 +25,7 @@
#define EAP_RADIUS_PLUGIN_H_
#include <plugins/plugin.h>
+#include <utils/enumerator.h>
typedef struct eap_radius_plugin_t eap_radius_plugin_t;
@@ -42,4 +43,11 @@ struct eap_radius_plugin_t {
plugin_t plugin;
};
+/**
+ * Create an enumerator over all loaded RADIUS servers.
+ *
+ * @return enumerator over radius_server_t
+ */
+enumerator_t *eap_radius_create_server_enumerator();
+
#endif /** EAP_RADIUS_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_client.c b/src/libcharon/plugins/eap_radius/radius_client.c
index 1d1f21742..232b9135e 100644
--- a/src/libcharon/plugins/eap_radius/radius_client.c
+++ b/src/libcharon/plugins/eap_radius/radius_client.c
@@ -15,6 +15,9 @@
#include "radius_client.h"
+#include "eap_radius_plugin.h"
+#include "radius_server.h"
+
#include <unistd.h>
#include <errno.h>
@@ -24,42 +27,8 @@
#include <threading/condvar.h>
#include <threading/mutex.h>
-/**
- * Default RADIUS server port, when not configured
- */
-#define RADIUS_PORT 1812
-
-/**
- * Vendor-Id of Microsoft specific attributes
- */
-#define VENDOR_ID_MICROSOFT 311
-
-/**
- * Microsoft specific vendor attributes
- */
-#define MS_MPPE_SEND_KEY 16
-#define MS_MPPE_RECV_KEY 17
-
typedef struct private_radius_client_t private_radius_client_t;
-typedef struct entry_t entry_t;
-
-/**
- * A socket pool entry.
- */
-struct entry_t {
- /** socket file descriptor */
- int fd;
- /** current RADIUS identifier */
- u_int8_t identifier;
- /** hasher to use for response verification */
- hasher_t *hasher;
- /** HMAC-MD5 signer to build Message-Authenticator attribute */
- signer_t *signer;
- /** random number generator for RADIUS request authenticator */
- rng_t *rng;
-};
-
/**
* Private data of an radius_client_t object.
*/
@@ -71,170 +40,20 @@ struct private_radius_client_t {
radius_client_t public;
/**
+ * Selected RADIUS server
+ */
+ radius_server_t *server;
+
+ /**
* RADIUS servers State attribute
*/
chunk_t state;
-};
-/**
- * Global list of radius sockets, contains entry_t's
- */
-static linked_list_t *sockets;
-
-/**
- * mutex to lock sockets list
- */
-static mutex_t *mutex;
-
-/**
- * condvar to wait for sockets
- */
-static condvar_t *condvar;
-
-/**
- * RADIUS secret
- */
-static chunk_t secret;
-
-/**
- * NAS-Identifier
- */
-static chunk_t nas_identifier;
-
-/**
- * Clean up socket list
- */
-void radius_client_cleanup()
-{
- entry_t *entry;
-
- mutex->destroy(mutex);
- condvar->destroy(condvar);
- while (sockets->remove_last(sockets, (void**)&entry) == SUCCESS)
- {
- entry->rng->destroy(entry->rng);
- entry->hasher->destroy(entry->hasher);
- entry->signer->destroy(entry->signer);
- close(entry->fd);
- free(entry);
- }
- sockets->destroy(sockets);
-}
-
-/**
- * Initialize the socket list
- */
-bool radius_client_init()
-{
- int i, count, fd;
- u_int16_t port;
- entry_t *entry;
- host_t *host;
- char *server;
-
- nas_identifier.ptr = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.nas_identifier", "strongSwan");
- nas_identifier.len = strlen(nas_identifier.ptr);
-
- secret.ptr = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.secret", NULL);
- if (!secret.ptr)
- {
- DBG1(DBG_CFG, "no RADUIS secret defined");
- return FALSE;
- }
- secret.len = strlen(secret.ptr);
- server = lib->settings->get_str(lib->settings,
- "charon.plugins.eap-radius.server", NULL);
- if (!server)
- {
- DBG1(DBG_CFG, "no RADUIS server defined");
- return FALSE;
- }
- port = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.port", RADIUS_PORT);
- host = host_create_from_dns(server, 0, port);
- if (!host)
- {
- return FALSE;
- }
- count = lib->settings->get_int(lib->settings,
- "charon.plugins.eap-radius.sockets", 1);
-
- sockets = linked_list_create();
- mutex = mutex_create(MUTEX_TYPE_DEFAULT);
- condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
- for (i = 0; i < count; i++)
- {
- fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP);
- if (fd < 0)
- {
- DBG1(DBG_CFG, "opening RADIUS socket failed");
- host->destroy(host);
- radius_client_cleanup();
- return FALSE;
- }
- if (connect(fd, host->get_sockaddr(host),
- *host->get_sockaddr_len(host)) < 0)
- {
- DBG1(DBG_CFG, "connecting RADIUS socket failed");
- host->destroy(host);
- radius_client_cleanup();
- return FALSE;
- }
- entry = malloc_thing(entry_t);
- entry->fd = fd;
- /* we use per-socket crypto elements: this reduces overhead, but
- * is still thread-save. */
- entry->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- entry->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
- entry->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!entry->hasher || !entry->signer || !entry->rng)
- {
- DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required");
- DESTROY_IF(entry->hasher);
- DESTROY_IF(entry->signer);
- DESTROY_IF(entry->rng);
- free(entry);
- host->destroy(host);
- radius_client_cleanup();
- return FALSE;
- }
- entry->signer->set_key(entry->signer, secret);
- /* we use a random identifier, helps if we restart often (testing) */
- entry->identifier = random();
- sockets->insert_last(sockets, entry);
- }
- host->destroy(host);
- return TRUE;
-}
-
-/**
- * Get a socket from the pool, block if none available
- */
-static entry_t* get_socket()
-{
- entry_t *entry;
-
- mutex->lock(mutex);
- while (sockets->remove_first(sockets, (void**)&entry) != SUCCESS)
- {
- condvar->wait(condvar, mutex);
- }
- mutex->unlock(mutex);
- return entry;
-}
-
-/**
- * Release a socket to the pool
- */
-static void put_socket(entry_t *entry)
-{
- mutex->lock(mutex);
- sockets->insert_last(sockets, entry);
- mutex->unlock(mutex);
- condvar->signal(condvar);
-}
+ /**
+ * EAP MSK, from MPPE keys
+ */
+ chunk_t msk;
+};
/**
* Save the state attribute to include in further request
@@ -261,234 +80,103 @@ static void save_state(private_radius_client_t *this, radius_message_t *msg)
chunk_free(&this->state);
}
-/**
- * Implementation of radius_client_t.request
- */
-static radius_message_t* request(private_radius_client_t *this,
- radius_message_t *req)
+METHOD(radius_client_t, request, radius_message_t*,
+ private_radius_client_t *this, radius_message_t *req)
{
char virtual[] = {0x00,0x00,0x00,0x05};
- entry_t *socket;
- chunk_t data;
- int i;
+ radius_socket_t *socket;
+ radius_message_t *res;
- socket = get_socket();
-
- /* set Message Identifier */
- req->set_identifier(req, socket->identifier++);
/* we add the "Virtual" NAS-Port-Type, as we SHOULD include one */
req->add(req, RAT_NAS_PORT_TYPE, chunk_create(virtual, sizeof(virtual)));
/* add our NAS-Identifier */
- req->add(req, RAT_NAS_IDENTIFIER, nas_identifier);
+ req->add(req, RAT_NAS_IDENTIFIER,
+ this->server->get_nas_identifier(this->server));
/* add State attribute, if server sent one */
if (this->state.ptr)
{
req->add(req, RAT_STATE, this->state);
}
- /* sign the request */
- req->sign(req, socket->rng, socket->signer);
-
- data = req->get_encoding(req);
- /* timeout after 2, 3, 4, 5 seconds */
- for (i = 2; i <= 5; i++)
+ socket = this->server->get_socket(this->server);
+ DBG1(DBG_CFG, "sending RADIUS %N to %#H", radius_message_code_names,
+ req->get_code(req), this->server->get_address(this->server));
+ res = socket->request(socket, req);
+ if (res)
{
- radius_message_t *response;
- bool retransmit = FALSE;
- struct timeval tv;
- char buf[4096];
- fd_set fds;
- int res;
-
- if (send(socket->fd, data.ptr, data.len, 0) != data.len)
- {
- DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
- put_socket(socket);
- return NULL;
- }
- tv.tv_sec = i;
- tv.tv_usec = 0;
-
- while (TRUE)
+ DBG1(DBG_CFG, "received RADIUS %N from %#H", radius_message_code_names,
+ res->get_code(res), this->server->get_address(this->server));
+ save_state(this, res);
+ if (res->get_code(res) == RMC_ACCESS_ACCEPT)
{
- FD_ZERO(&fds);
- FD_SET(socket->fd, &fds);
- res = select(socket->fd + 1, &fds, NULL, NULL, &tv);
- /* TODO: updated tv to time not waited. Linux does this for us. */
- if (res < 0)
- { /* failed */
- DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
- strerror(errno));
- break;
- }
- if (res == 0)
- { /* timeout */
- DBG1(DBG_CFG, "retransmitting RADIUS message");
- retransmit = TRUE;
- break;
- }
- res = recv(socket->fd, buf, sizeof(buf), MSG_DONTWAIT);
- if (res <= 0)
- {
- DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
- strerror(errno));
- break;
- }
- response = radius_message_parse_response(chunk_create(buf, res));
- if (response)
- {
- if (response->verify(response, req->get_authenticator(req),
- secret, socket->hasher, socket->signer))
- {
- save_state(this, response);
- put_socket(socket);
- return response;
- }
- response->destroy(response);
- }
- DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
- }
- if (!retransmit)
- {
- break;
+ chunk_clear(&this->msk);
+ this->msk = socket->decrypt_msk(socket, req, res);
}
+ this->server->put_socket(this->server, socket, TRUE);
+ return res;
}
- DBG1(DBG_CFG, "RADIUS server is not responding");
- put_socket(socket);
+ this->server->put_socket(this->server, socket, FALSE);
charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING);
return NULL;
}
-/**
- * Decrypt a MS-MPPE-Send/Recv-Key
- */
-static chunk_t decrypt_mppe_key(private_radius_client_t *this, u_int16_t salt,
- chunk_t C, radius_message_t *request)
+METHOD(radius_client_t, get_msk, chunk_t,
+ private_radius_client_t *this)
{
- chunk_t A, R, P, seed;
- u_char *c, *p;
- hasher_t *hasher;
-
- /**
- * From RFC2548 (encryption):
- * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1)
- * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2)
- * . . .
- * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i)
- */
-
- if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5)
- {
- return chunk_empty;
- }
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
- if (!hasher)
- {
- return chunk_empty;
- }
-
- A = chunk_create((u_char*)&salt, sizeof(salt));
- R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5);
- P = chunk_alloca(C.len);
- p = P.ptr;
- c = C.ptr;
-
- seed = chunk_cata("cc", R, A);
-
- while (c < C.ptr + C.len)
- {
- /* b(i) = MD5(S + c(i-1)) */
- hasher->get_hash(hasher, secret, NULL);
- hasher->get_hash(hasher, seed, p);
-
- /* p(i) = b(i) xor c(1) */
- memxor(p, c, HASH_SIZE_MD5);
-
- /* prepare next round */
- seed = chunk_create(c, HASH_SIZE_MD5);
- c += HASH_SIZE_MD5;
- p += HASH_SIZE_MD5;
- }
- hasher->destroy(hasher);
+ return this->msk;
+}
- /* remove truncation, first byte is key length */
- if (*P.ptr >= P.len)
- { /* decryption failed? */
- return chunk_empty;
- }
- return chunk_clone(chunk_create(P.ptr + 1, *P.ptr));
+METHOD(radius_client_t, destroy, void,
+ private_radius_client_t *this)
+{
+ chunk_clear(&this->msk);
+ free(this->state.ptr);
+ free(this);
}
/**
- * Implementation of radius_client_t.decrypt_msk
+ * See header
*/
-static chunk_t decrypt_msk(private_radius_client_t *this,
- radius_message_t *response, radius_message_t *request)
+radius_client_t *radius_client_create()
{
- struct {
- u_int32_t id;
- u_int8_t type;
- u_int8_t length;
- u_int16_t salt;
- u_int8_t key[];
- } __attribute__((packed)) *mppe_key;
+ private_radius_client_t *this;
enumerator_t *enumerator;
- chunk_t data, send = chunk_empty, recv = chunk_empty;
- int type;
-
- enumerator = response->create_enumerator(response);
- while (enumerator->enumerate(enumerator, &type, &data))
+ radius_server_t *server;
+ int current, best = -1;
+
+ INIT(this,
+ .public = {
+ .request = _request,
+ .get_msk = _get_msk,
+ .destroy = _destroy,
+ },
+ );
+
+ enumerator = eap_radius_create_server_enumerator();
+ while (enumerator->enumerate(enumerator, &server))
{
- if (type == RAT_VENDOR_SPECIFIC &&
- data.len > sizeof(*mppe_key))
+ current = server->get_preference(server);
+ if (current > best ||
+ /* for two with equal preference, 50-50 chance */
+ (current == best && random() % 2 == 0))
+ {
+ DBG2(DBG_CFG, "RADIUS server %H is candidate: %d",
+ server->get_address(server), current);
+ best = current;
+ this->server = server;
+ }
+ else
{
- mppe_key = (void*)data.ptr;
- if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT &&
- mppe_key->length == data.len - sizeof(mppe_key->id))
- {
- data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key));
- if (mppe_key->type == MS_MPPE_SEND_KEY)
- {
- send = decrypt_mppe_key(this, mppe_key->salt, data, request);
- }
- if (mppe_key->type == MS_MPPE_RECV_KEY)
- {
- recv = decrypt_mppe_key(this, mppe_key->salt, data, request);
- }
- }
+ DBG2(DBG_CFG, "RADIUS server %H skipped: %d",
+ server->get_address(server), current);
}
}
enumerator->destroy(enumerator);
- if (send.ptr && recv.ptr)
+
+ if (!this->server)
{
- return chunk_cat("mm", recv, send);
+ free(this);
+ return NULL;
}
- chunk_clear(&send);
- chunk_clear(&recv);
- return chunk_empty;
-}
-
-/**
- * Implementation of radius_client_t.destroy.
- */
-static void destroy(private_radius_client_t *this)
-{
- free(this->state.ptr);
- free(this);
-}
-
-/**
- * See header
- */
-radius_client_t *radius_client_create()
-{
- private_radius_client_t *this = malloc_thing(private_radius_client_t);
-
- this->public.request = (radius_message_t*(*)(radius_client_t*, radius_message_t *msg))request;
- this->public.decrypt_msk = (chunk_t(*)(radius_client_t*, radius_message_t *, radius_message_t *))decrypt_msk;
- this->public.destroy = (void(*)(radius_client_t*))destroy;
-
- this->state = chunk_empty;
return &this->public;
}
diff --git a/src/libcharon/plugins/eap_radius/radius_client.h b/src/libcharon/plugins/eap_radius/radius_client.h
index 77ba94807..e4f3a7222 100644
--- a/src/libcharon/plugins/eap_radius/radius_client.h
+++ b/src/libcharon/plugins/eap_radius/radius_client.h
@@ -29,19 +29,14 @@ typedef struct radius_client_t radius_client_t;
* RADIUS client functionality.
*
* To communicate with a RADIUS server, create a client and send messages over
- * it. All instances share a fixed size pool of sockets. The client reserves
- * a socket during request() and releases it afterwards.
+ * it. The client allocates a socket from the best RADIUS server abailable.
*/
struct radius_client_t {
/**
* Send a RADIUS request and wait for the response.
*
- * The client fills in RADIUS Message identifier, NAS-Identifier,
- * NAS-Port-Type, builds a Request-Authenticator and calculates the
- * Message-Authenticator attribute.
- * The received response gets verified using the Response-Identifier
- * and the Message-Authenticator attribute.
+ * The client fills in NAS-Identifier nad NAS-Port-Type
*
* @param msg RADIUS request message to send
* @return response, NULL if timed out/verification failed
@@ -49,14 +44,11 @@ struct radius_client_t {
radius_message_t* (*request)(radius_client_t *this, radius_message_t *msg);
/**
- * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key.
+ * Get the EAP MSK after successful RADIUS authentication.
*
- * @param response RADIUS response message containing attributes
- * @param request associated RADIUS request message
- * @return allocated MSK, empty chunk if none found
+ * @return MSK, allocated
*/
- chunk_t (*decrypt_msk)(radius_client_t *this, radius_message_t *response,
- radius_message_t *request);
+ chunk_t (*get_msk)(radius_client_t *this);
/**
* Destroy the client, release the socket.
@@ -65,24 +57,10 @@ struct radius_client_t {
};
/**
- * Create a RADIUS client, acquire a socket.
- *
- * This call might block if the socket pool is empty.
+ * Create a RADIUS client.
*
* @return radius_client_t object
*/
radius_client_t *radius_client_create();
-/**
- * Initialize the socket pool.
- *
- * @return TRUE if initialization successful
- */
-bool radius_client_init();
-
-/**
- * Cleanup the socket pool.
- */
-void radius_client_cleanup();
-
#endif /** RADIUS_CLIENT_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_message.c b/src/libcharon/plugins/eap_radius/radius_message.c
index 11a1d8dfc..23a29b772 100644
--- a/src/libcharon/plugins/eap_radius/radius_message.c
+++ b/src/libcharon/plugins/eap_radius/radius_message.c
@@ -215,13 +215,8 @@ typedef struct {
int left;
} attribute_enumerator_t;
-
-/**
- * Implementation of attribute_enumerator_t.enumerate
- */
-static bool attribute_enumerate(attribute_enumerator_t *this,
- int *type, chunk_t *data)
-
+METHOD(enumerator_t, attribute_enumerate, bool,
+ attribute_enumerator_t *this, int *type, chunk_t *data)
{
if (this->left == 0)
{
@@ -241,10 +236,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
return TRUE;
}
-/**
- * Implementation of radius_message_t.create_enumerator
- */
-static enumerator_t* create_enumerator(private_radius_message_t *this)
+METHOD(radius_message_t, create_enumerator, enumerator_t*,
+ private_radius_message_t *this)
{
attribute_enumerator_t *e;
@@ -252,20 +245,19 @@ static enumerator_t* create_enumerator(private_radius_message_t *this)
{
return enumerator_create_empty();
}
-
- e = malloc_thing(attribute_enumerator_t);
- e->public.enumerate = (void*)attribute_enumerate;
- e->public.destroy = (void*)free;
- e->next = (rattr_t*)this->msg->attributes;
- e->left = ntohs(this->msg->length) - sizeof(rmsg_t);
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_attribute_enumerate,
+ .destroy = (void*)free,
+ },
+ .next = (rattr_t*)this->msg->attributes,
+ .left = ntohs(this->msg->length) - sizeof(rmsg_t),
+ );
return &e->public;
}
-/**
- * Implementation of radius_message_t.add
- */
-static void add(private_radius_message_t *this, radius_attribute_type_t type,
- chunk_t data)
+METHOD(radius_message_t, add, void,
+ private_radius_message_t *this, radius_attribute_type_t type, chunk_t data)
{
rattr_t *attribute;
@@ -279,10 +271,8 @@ static void add(private_radius_message_t *this, radius_attribute_type_t type,
this->msg->length = htons(ntohs(this->msg->length) + attribute->length);
}
-/**
- * Implementation of radius_message_t.sign
- */
-static void sign(private_radius_message_t *this, rng_t *rng, signer_t *signer)
+METHOD(radius_message_t, sign, void,
+ private_radius_message_t *this, rng_t *rng, signer_t *signer)
{
char buf[HASH_SIZE_MD5];
@@ -297,11 +287,9 @@ static void sign(private_radius_message_t *this, rng_t *rng, signer_t *signer)
((u_char*)this->msg) + ntohs(this->msg->length) - HASH_SIZE_MD5);
}
-/**
- * Implementation of radius_message_t.verify
- */
-static bool verify(private_radius_message_t *this, u_int8_t *req_auth,
- chunk_t secret, hasher_t *hasher, signer_t *signer)
+METHOD(radius_message_t, verify, bool,
+ private_radius_message_t *this, u_int8_t *req_auth, chunk_t secret,
+ hasher_t *hasher, signer_t *signer)
{
char buf[HASH_SIZE_MD5], res_auth[HASH_SIZE_MD5];
enumerator_t *enumerator;
@@ -369,51 +357,39 @@ static bool verify(private_radius_message_t *this, u_int8_t *req_auth,
return TRUE;
}
-/**
- * Implementation of radius_message_t.get_code
- */
-static radius_message_code_t get_code(private_radius_message_t *this)
+METHOD(radius_message_t, get_code, radius_message_code_t,
+ private_radius_message_t *this)
{
return this->msg->code;
}
-/**
- * Implementation of radius_message_t.get_identifier
- */
-static u_int8_t get_identifier(private_radius_message_t *this)
+METHOD(radius_message_t, get_identifier, u_int8_t,
+ private_radius_message_t *this)
{
return this->msg->identifier;
}
-/**
- * Implementation of radius_message_t.set_identifier
- */
-static void set_identifier(private_radius_message_t *this, u_int8_t identifier)
+METHOD(radius_message_t, set_identifier, void,
+ private_radius_message_t *this, u_int8_t identifier)
{
this->msg->identifier = identifier;
}
-/**
- * Implementation of radius_message_t.get_authenticator
- */
-static u_int8_t* get_authenticator(private_radius_message_t *this)
+METHOD(radius_message_t, get_authenticator, u_int8_t*,
+ private_radius_message_t *this)
{
return this->msg->authenticator;
}
-/**
- * Implementation of radius_message_t.get_encoding
- */
-static chunk_t get_encoding(private_radius_message_t *this)
+METHOD(radius_message_t, get_encoding, chunk_t,
+ private_radius_message_t *this)
{
return chunk_create((u_char*)this->msg, ntohs(this->msg->length));
}
-/**
- * Implementation of radius_message_t.destroy.
- */
-static void destroy(private_radius_message_t *this)
+METHOD(radius_message_t, destroy, void,
+ private_radius_message_t *this)
{
free(this->msg);
free(this);
@@ -424,18 +400,22 @@ static void destroy(private_radius_message_t *this)
*/
static private_radius_message_t *radius_message_create()
{
- private_radius_message_t *this = malloc_thing(private_radius_message_t);
-
- this->public.create_enumerator = (enumerator_t*(*)(radius_message_t*))create_enumerator;
- this->public.add = (void(*)(radius_message_t*, radius_attribute_type_t,chunk_t))add;
- this->public.get_code = (radius_message_code_t(*)(radius_message_t*))get_code;
- this->public.get_identifier = (u_int8_t(*)(radius_message_t*))get_identifier;
- this->public.set_identifier = (void(*)(radius_message_t*, u_int8_t identifier))set_identifier;
- this->public.get_authenticator = (u_int8_t*(*)(radius_message_t*))get_authenticator;
- this->public.get_encoding = (chunk_t(*)(radius_message_t*))get_encoding;
- this->public.sign = (void(*)(radius_message_t*, rng_t *rng, signer_t *signer))sign;
- this->public.verify = (bool(*)(radius_message_t*, u_int8_t *req_auth, chunk_t secret, hasher_t *hasher, signer_t *signer))verify;
- this->public.destroy = (void(*)(radius_message_t*))destroy;
+ private_radius_message_t *this;
+
+ INIT(this,
+ .public = {
+ .create_enumerator = _create_enumerator,
+ .add = _add,
+ .get_code = _get_code,
+ .get_identifier = _get_identifier,
+ .set_identifier = _set_identifier,
+ .get_authenticator = _get_authenticator,
+ .get_encoding = _get_encoding,
+ .sign = _sign,
+ .verify = _verify,
+ .destroy = _destroy,
+ },
+ );
return this;
}
@@ -447,10 +427,11 @@ radius_message_t *radius_message_create_request()
{
private_radius_message_t *this = radius_message_create();
- this->msg = malloc_thing(rmsg_t);
- this->msg->code = RMC_ACCESS_REQUEST;
- this->msg->identifier = 0;
- this->msg->length = htons(sizeof(rmsg_t));
+ INIT(this->msg,
+ .code = RMC_ACCESS_REQUEST,
+ .identifier = 0,
+ .length = htons(sizeof(rmsg_t)),
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/eap_radius/radius_server.c b/src/libcharon/plugins/eap_radius/radius_server.c
new file mode 100644
index 000000000..f54b8b2cd
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_server.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "radius_server.h"
+
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <utils/linked_list.h>
+
+typedef struct private_radius_server_t private_radius_server_t;
+
+/**
+ * Private data of an radius_server_t object.
+ */
+struct private_radius_server_t {
+
+ /**
+ * Public radius_server_t interface.
+ */
+ radius_server_t public;
+
+ /**
+ * RADIUS server address
+ */
+ host_t *host;
+
+ /**
+ * list of radius sockets, as radius_socket_t
+ */
+ linked_list_t *sockets;
+
+ /**
+ * Total number of sockets, in list + currently in use
+ */
+ int socket_count;
+
+ /**
+ * mutex to lock sockets list
+ */
+ mutex_t *mutex;
+
+ /**
+ * condvar to wait for sockets
+ */
+ condvar_t *condvar;
+
+ /**
+ * RADIUS secret
+ */
+ chunk_t secret;
+
+ /**
+ * NAS-Identifier
+ */
+ chunk_t nas_identifier;
+
+ /**
+ * Preference boost for this server
+ */
+ int preference;
+
+ /**
+ * Is the server currently reachable
+ */
+ bool reachable;
+
+ /**
+ * Retry counter for unreachable servers
+ */
+ int retry;
+};
+
+METHOD(radius_server_t, get_socket, radius_socket_t*,
+ private_radius_server_t *this)
+{
+ radius_socket_t *skt;
+
+ this->mutex->lock(this->mutex);
+ while (this->sockets->remove_first(this->sockets, (void**)&skt) != SUCCESS)
+ {
+ this->condvar->wait(this->condvar, this->mutex);
+ }
+ this->mutex->unlock(this->mutex);
+ return skt;
+}
+
+METHOD(radius_server_t, put_socket, void,
+ private_radius_server_t *this, radius_socket_t *skt, bool result)
+{
+ this->mutex->lock(this->mutex);
+ this->sockets->insert_last(this->sockets, skt);
+ this->mutex->unlock(this->mutex);
+ this->condvar->signal(this->condvar);
+ this->reachable = result;
+}
+
+METHOD(radius_server_t, get_nas_identifier, chunk_t,
+ private_radius_server_t *this)
+{
+ return this->nas_identifier;
+}
+
+METHOD(radius_server_t, get_preference, int,
+ private_radius_server_t *this)
+{
+ int pref;
+
+ if (this->socket_count == 0)
+ { /* don't have sockets, huh? */
+ return -1;
+ }
+ /* calculate preference between 0-100 + boost */
+ pref = this->preference;
+ pref += this->sockets->get_count(this->sockets) * 100 / this->socket_count;
+ if (this->reachable)
+ { /* reachable server get a boost: pref = 110-210 + boost */
+ return pref + 110;
+ }
+ /* Not reachable. Increase preference randomly to let it retry from
+ * time to time, especially if other servers have high load. */
+ this->retry++;
+ if (this->retry % 128 == 0)
+ { /* every 64th request gets 210, same as unloaded reachable */
+ return pref + 110;
+ }
+ if (this->retry % 32 == 0)
+ { /* every 32th request gets 190, wins against average loaded */
+ return pref + 90;
+ }
+ if (this->retry % 8 == 0)
+ { /* every 8th request gets 110, same as server under load */
+ return pref + 10;
+ }
+ /* other get ~100, less than fully loaded */
+ return pref;
+}
+
+METHOD(radius_server_t, get_address, host_t*,
+ private_radius_server_t *this)
+{
+ return this->host;
+}
+
+METHOD(radius_server_t, destroy, void,
+ private_radius_server_t *this)
+{
+ DESTROY_IF(this->host);
+ this->mutex->destroy(this->mutex);
+ this->condvar->destroy(this->condvar);
+ this->sockets->destroy_offset(this->sockets,
+ offsetof(radius_socket_t, destroy));
+ free(this);
+}
+
+/**
+ * See header
+ */
+radius_server_t *radius_server_create(char *server, u_int16_t port,
+ char *nas_identifier, char *secret, int sockets, int preference)
+{
+ private_radius_server_t *this;
+ radius_socket_t *socket;
+
+ INIT(this,
+ .public = {
+ .get_socket = _get_socket,
+ .put_socket = _put_socket,
+ .get_nas_identifier = _get_nas_identifier,
+ .get_preference = _get_preference,
+ .get_address = _get_address,
+ .destroy = _destroy,
+ },
+ .reachable = TRUE,
+ .nas_identifier = chunk_create(nas_identifier, strlen(nas_identifier)),
+ .socket_count = sockets,
+ .sockets = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .host = host_create_from_dns(server, 0, port),
+ .preference = preference,
+ );
+
+ if (!this->host)
+ {
+ destroy(this);
+ return NULL;
+ }
+ while (sockets--)
+ {
+ socket = radius_socket_create(this->host,
+ chunk_create(secret, strlen(secret)));
+ if (!socket)
+ {
+ destroy(this);
+ return NULL;
+ }
+ this->sockets->insert_last(this->sockets, socket);
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_radius/radius_server.h b/src/libcharon/plugins/eap_radius/radius_server.h
new file mode 100644
index 000000000..b820cb583
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_server.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup radius_server radius_server
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef RADIUS_SERVER_H_
+#define RADIUS_SERVER_H_
+
+typedef struct radius_server_t radius_server_t;
+
+#include "radius_socket.h"
+
+/**
+ * RADIUS server configuration.
+ */
+struct radius_server_t {
+
+ /**
+ * Get a RADIUS socket from the pool to communicate with this server.
+ *
+ * @return RADIUS socket
+ */
+ radius_socket_t* (*get_socket)(radius_server_t *this);
+
+ /**
+ * Release a socket to the pool after use.
+ *
+ * @param skt RADIUS socket to release
+ * @param result result of the socket use, TRUE for success
+ */
+ void (*put_socket)(radius_server_t *this, radius_socket_t *skt, bool result);
+
+ /**
+ * Get the NAS-Identifier to use with this server.
+ *
+ * @return NAS-Identifier, internal data
+ */
+ chunk_t (*get_nas_identifier)(radius_server_t *this);
+
+ /**
+ * Get the preference of this server.
+ *
+ * Based on the available sockets and the server reachability a preference
+ * value is calculated: better servers return a higher value.
+ */
+ int (*get_preference)(radius_server_t *this);
+
+ /**
+ * Get the address of the RADIUS server.
+ *
+ * @return address, internal data
+ */
+ host_t* (*get_address)(radius_server_t *this);
+
+ /**
+ * Destroy a radius_server_t.
+ */
+ void (*destroy)(radius_server_t *this);
+};
+
+/**
+ * Create a radius_server instance.
+ *
+ * @param server server address
+ * @param port server port
+ * @param nas_identifier NAS-Identifier to use with this server
+ * @param sockets number of sockets to create in pool
+ * @param preference preference boost for this server
+ */
+radius_server_t *radius_server_create(char *server, u_int16_t port,
+ char *nas_identifier, char *secret, int sockets, int preference);
+
+#endif /** RADIUS_SERVER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_radius/radius_socket.c b/src/libcharon/plugins/eap_radius/radius_socket.c
new file mode 100644
index 000000000..f46c27ede
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_socket.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "radius_socket.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <debug.h>
+
+/**
+ * Vendor-Id of Microsoft specific attributes
+ */
+#define VENDOR_ID_MICROSOFT 311
+
+/**
+ * Microsoft specific vendor attributes
+ */
+#define MS_MPPE_SEND_KEY 16
+#define MS_MPPE_RECV_KEY 17
+
+typedef struct private_radius_socket_t private_radius_socket_t;
+
+/**
+ * Private data of an radius_socket_t object.
+ */
+struct private_radius_socket_t {
+
+ /**
+ * Public radius_socket_t interface.
+ */
+ radius_socket_t public;
+
+ /**
+ * socket file descriptor
+ */
+ int fd;
+
+ /**
+ * current RADIUS identifier
+ */
+ u_int8_t identifier;
+
+ /**
+ * hasher to use for response verification
+ */
+ hasher_t *hasher;
+
+ /**
+ * HMAC-MD5 signer to build Message-Authenticator attribute
+ */
+ signer_t *signer;
+
+ /**
+ * random number generator for RADIUS request authenticator
+ */
+ rng_t *rng;
+
+ /**
+ * RADIUS secret
+ */
+ chunk_t secret;
+};
+
+METHOD(radius_socket_t, request, radius_message_t*,
+ private_radius_socket_t *this, radius_message_t *request)
+{
+ chunk_t data;
+ int i;
+
+ /* set Message Identifier */
+ request->set_identifier(request, this->identifier++);
+ /* sign the request */
+ request->sign(request, this->rng, this->signer);
+
+ data = request->get_encoding(request);
+ /* timeout after 2, 3, 4, 5 seconds */
+ for (i = 2; i <= 5; i++)
+ {
+ radius_message_t *response;
+ bool retransmit = FALSE;
+ struct timeval tv;
+ char buf[4096];
+ fd_set fds;
+ int res;
+
+ if (send(this->fd, data.ptr, data.len, 0) != data.len)
+ {
+ DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
+ return NULL;
+ }
+ tv.tv_sec = i;
+ tv.tv_usec = 0;
+
+ while (TRUE)
+ {
+ FD_ZERO(&fds);
+ FD_SET(this->fd, &fds);
+ res = select(this->fd + 1, &fds, NULL, NULL, &tv);
+ /* TODO: updated tv to time not waited. Linux does this for us. */
+ if (res < 0)
+ { /* failed */
+ DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
+ strerror(errno));
+ break;
+ }
+ if (res == 0)
+ { /* timeout */
+ DBG1(DBG_CFG, "retransmitting RADIUS message");
+ retransmit = TRUE;
+ break;
+ }
+ res = recv(this->fd, buf, sizeof(buf), MSG_DONTWAIT);
+ if (res <= 0)
+ {
+ DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
+ strerror(errno));
+ break;
+ }
+ response = radius_message_parse_response(chunk_create(buf, res));
+ if (response)
+ {
+ if (response->verify(response,
+ request->get_authenticator(request), this->secret,
+ this->hasher, this->signer))
+ {
+ return response;
+ }
+ response->destroy(response);
+ }
+ DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+ }
+ if (!retransmit)
+ {
+ break;
+ }
+ }
+ DBG1(DBG_CFG, "RADIUS server is not responding");
+ return NULL;
+}
+
+/**
+ * Decrypt a MS-MPPE-Send/Recv-Key
+ */
+static chunk_t decrypt_mppe_key(private_radius_socket_t *this, u_int16_t salt,
+ chunk_t C, radius_message_t *request)
+{
+ chunk_t A, R, P, seed;
+ u_char *c, *p;
+
+ /**
+ * From RFC2548 (encryption):
+ * b(1) = MD5(S + R + A) c(1) = p(1) xor b(1) C = c(1)
+ * b(2) = MD5(S + c(1)) c(2) = p(2) xor b(2) C = C + c(2)
+ * . . .
+ * b(i) = MD5(S + c(i-1)) c(i) = p(i) xor b(i) C = C + c(i)
+ */
+
+ if (C.len % HASH_SIZE_MD5 || C.len < HASH_SIZE_MD5)
+ {
+ return chunk_empty;
+ }
+
+ A = chunk_create((u_char*)&salt, sizeof(salt));
+ R = chunk_create(request->get_authenticator(request), HASH_SIZE_MD5);
+ P = chunk_alloca(C.len);
+ p = P.ptr;
+ c = C.ptr;
+
+ seed = chunk_cata("cc", R, A);
+
+ while (c < C.ptr + C.len)
+ {
+ /* b(i) = MD5(S + c(i-1)) */
+ this->hasher->get_hash(this->hasher, this->secret, NULL);
+ this->hasher->get_hash(this->hasher, seed, p);
+
+ /* p(i) = b(i) xor c(1) */
+ memxor(p, c, HASH_SIZE_MD5);
+
+ /* prepare next round */
+ seed = chunk_create(c, HASH_SIZE_MD5);
+ c += HASH_SIZE_MD5;
+ p += HASH_SIZE_MD5;
+ }
+
+ /* remove truncation, first byte is key length */
+ if (*P.ptr >= P.len)
+ { /* decryption failed? */
+ return chunk_empty;
+ }
+ return chunk_clone(chunk_create(P.ptr + 1, *P.ptr));
+}
+
+METHOD(radius_socket_t, decrypt_msk, chunk_t,
+ private_radius_socket_t *this, radius_message_t *request,
+ radius_message_t *response)
+{
+ struct {
+ u_int32_t id;
+ u_int8_t type;
+ u_int8_t length;
+ u_int16_t salt;
+ u_int8_t key[];
+ } __attribute__((packed)) *mppe_key;
+ enumerator_t *enumerator;
+ chunk_t data, send = chunk_empty, recv = chunk_empty;
+ int type;
+
+ enumerator = response->create_enumerator(response);
+ while (enumerator->enumerate(enumerator, &type, &data))
+ {
+ if (type == RAT_VENDOR_SPECIFIC &&
+ data.len > sizeof(*mppe_key))
+ {
+ mppe_key = (void*)data.ptr;
+ if (ntohl(mppe_key->id) == VENDOR_ID_MICROSOFT &&
+ mppe_key->length == data.len - sizeof(mppe_key->id))
+ {
+ data = chunk_create(mppe_key->key, data.len - sizeof(*mppe_key));
+ if (mppe_key->type == MS_MPPE_SEND_KEY)
+ {
+ send = decrypt_mppe_key(this, mppe_key->salt, data, request);
+ }
+ if (mppe_key->type == MS_MPPE_RECV_KEY)
+ {
+ recv = decrypt_mppe_key(this, mppe_key->salt, data, request);
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (send.ptr && recv.ptr)
+ {
+ return chunk_cat("mm", recv, send);
+ }
+ chunk_clear(&send);
+ chunk_clear(&recv);
+ return chunk_empty;
+}
+
+METHOD(radius_socket_t, destroy, void,
+ private_radius_socket_t *this)
+{
+ DESTROY_IF(this->hasher);
+ DESTROY_IF(this->signer);
+ DESTROY_IF(this->rng);
+ close(this->fd);
+ free(this);
+}
+
+/**
+ * See header
+ */
+radius_socket_t *radius_socket_create(host_t *host, chunk_t secret)
+{
+ private_radius_socket_t *this;
+
+ INIT(this,
+ .public = {
+ .request = _request,
+ .decrypt_msk = _decrypt_msk,
+ .destroy = _destroy,
+ },
+ );
+
+ this->fd = socket(host->get_family(host), SOCK_DGRAM, IPPROTO_UDP);
+ if (this->fd < 0)
+ {
+ DBG1(DBG_CFG, "opening RADIUS socket failed: %s", strerror(errno));
+ free(this);
+ return NULL;
+ }
+ if (connect(this->fd, host->get_sockaddr(host),
+ *host->get_sockaddr_len(host)) < 0)
+ {
+ DBG1(DBG_CFG, "connecting RADIUS socket failed");
+ close(this->fd);
+ free(this);
+ return NULL;
+ }
+ this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
+ this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!this->hasher || !this->signer || !this->rng)
+ {
+ DBG1(DBG_CFG, "RADIUS initialization failed, HMAC/MD5/RNG required");
+ destroy(this);
+ return NULL;
+ }
+ this->secret = secret;
+ this->signer->set_key(this->signer, secret);
+ /* we use a random identifier, helps if we restart often */
+ this->identifier = random();
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_radius/radius_socket.h b/src/libcharon/plugins/eap_radius/radius_socket.h
new file mode 100644
index 000000000..fe8491a8f
--- /dev/null
+++ b/src/libcharon/plugins/eap_radius/radius_socket.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup radius_socket radius_socket
+ * @{ @ingroup eap_radius
+ */
+
+#ifndef RADIUS_SOCKET_H_
+#define RADIUS_SOCKET_H_
+
+typedef struct radius_socket_t radius_socket_t;
+
+#include "radius_message.h"
+
+#include <utils/host.h>
+
+/**
+ * RADIUS socket to a server.
+ */
+struct radius_socket_t {
+
+ /**
+ * Send a RADIUS request, wait for response.
+
+ * The socket fills in RADIUS Message identifier, builds a
+ * Request-Authenticator and calculates the Message-Authenticator
+ * attribute.
+ * The received response gets verified using the Response-Identifier
+ * and the Message-Authenticator attribute.
+ *
+ * @param request request message
+ * @return response message, NULL if timed out
+ */
+ radius_message_t* (*request)(radius_socket_t *this,
+ radius_message_t *request);
+
+ /**
+ * Decrypt the MSK encoded in a messages MS-MPPE-Send/Recv-Key.
+ *
+ * @param request associated RADIUS request message
+ * @param response RADIUS response message containing attributes
+ * @return allocated MSK, empty chunk if none found
+ */
+ chunk_t (*decrypt_msk)(radius_socket_t *this, radius_message_t *request,
+ radius_message_t *response);
+
+ /**
+ * Destroy a radius_socket_t.
+ */
+ void (*destroy)(radius_socket_t *this);
+};
+
+/**
+ * Create a radius_socket instance.
+ *
+ * @param host RADIUS server address to connect to
+ * @param secret RADIUS secret
+ */
+radius_socket_t *radius_socket_create(host_t *host, chunk_t secret);
+
+#endif /** RADIUS_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index 588965113..d0f44e925 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
index 961cfd30d..a3506f4ba 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
@@ -484,7 +484,6 @@ static status_t process_notification(private_eap_sim_peer_t *this,
/* test success bit */
if (!(data.ptr[0] & 0x80))
{
- success = FALSE;
DBG1(DBG_IKE, "received EAP-SIM notification error '%N'",
simaka_notification_names, code);
}
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index 2d998dbcc..2aa0ac832 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 6c44ea2bb..7d80f8019 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 35d8e7c3b..fc26f4497 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
new file mode 100644
index 000000000..73768be0e
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+endif
+
+libstrongswan_eap_simaka_sql_la_SOURCES = \
+ eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \
+ eap_simaka_sql_card.h eap_simaka_sql_card.c \
+ eap_simaka_sql_provider.h eap_simaka_sql_provider.c
+
+libstrongswan_eap_simaka_sql_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
new file mode 100644
index 000000000..f2e82df0a
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -0,0 +1,592 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/eap_simaka_sql
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_eap_simaka_sql_la_LIBADD =
+am_libstrongswan_eap_simaka_sql_la_OBJECTS = eap_simaka_sql_plugin.lo \
+ eap_simaka_sql_card.lo eap_simaka_sql_provider.lo
+libstrongswan_eap_simaka_sql_la_OBJECTS = \
+ $(am_libstrongswan_eap_simaka_sql_la_OBJECTS)
+libstrongswan_eap_simaka_sql_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libstrongswan_eap_simaka_sql_la_LDFLAGS) $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_eap_simaka_sql_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_eap_simaka_sql_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_eap_simaka_sql_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_eap_simaka_sql_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+libstrongswan_eap_simaka_sql_la_SOURCES = \
+ eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \
+ eap_simaka_sql_card.h eap_simaka_sql_card.c \
+ eap_simaka_sql_provider.h eap_simaka_sql_provider.c
+
+libstrongswan_eap_simaka_sql_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_sql/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/eap_simaka_sql/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-eap-simaka-sql.la: $(libstrongswan_eap_simaka_sql_la_OBJECTS) $(libstrongswan_eap_simaka_sql_la_DEPENDENCIES)
+ $(libstrongswan_eap_simaka_sql_la_LINK) $(am_libstrongswan_eap_simaka_sql_la_rpath) $(libstrongswan_eap_simaka_sql_la_OBJECTS) $(libstrongswan_eap_simaka_sql_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_card.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eap_simaka_sql_provider.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
new file mode 100644
index 000000000..b7590405f
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_card.h"
+
+#include <time.h>
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_card_t private_eap_simaka_sql_card_t;
+
+/**
+ * Private data of an eap_simaka_sql_card_t object.
+ */
+struct private_eap_simaka_sql_card_t {
+
+ /**
+ * Public eap_simaka_sql_card_t interface.
+ */
+ eap_simaka_sql_card_t public;
+
+ /**
+ * Triplet/quintuplet database
+ */
+ database_t *db;
+
+ /**
+ * Remove used triplets/quintuplets from database
+ */
+ bool remove_used;
+};
+
+METHOD(sim_card_t, get_triplet, bool,
+ private_eap_simaka_sql_card_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
+{
+ chunk_t sres_chunk, kc_chunk;
+ enumerator_t *query;
+ bool found = FALSE;
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%Y", id);
+ query = this->db->query(this->db,
+ "select sres, kc from triplets where rand = ? and id = ? "
+ "order by use limit 1",
+ DB_BLOB, chunk_create(rand, SIM_RAND_LEN), DB_TEXT, buf,
+ DB_BLOB, DB_BLOB);
+ if (query)
+ {
+ if (query->enumerate(query, &sres_chunk, &kc_chunk))
+ {
+ if (sres_chunk.len == SIM_SRES_LEN &&
+ kc_chunk.len == SIM_KC_LEN)
+ {
+ memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN);
+ memcpy(kc, kc_chunk.ptr, SIM_KC_LEN);
+ found = TRUE;
+ }
+ }
+ query->destroy(query);
+ }
+ if (found)
+ {
+ if (this->remove_used)
+ {
+ this->db->execute(this->db, NULL,
+ "delete from triplets where id = ? and rand = ?",
+ DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ else
+ {
+ this->db->execute(this->db, NULL,
+ "update triplets set use = ? where id = ? and rand = ?",
+ DB_UINT, time(NULL), DB_TEXT, buf,
+ DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ }
+ return found;
+}
+
+METHOD(sim_card_t, get_quintuplet, status_t,
+ private_eap_simaka_sql_card_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
+ char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len)
+{
+ chunk_t ck_chunk, ik_chunk, res_chunk;
+ enumerator_t *query;
+ status_t found = FAILED;
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%Y", id);
+ query = this->db->query(this->db, "select ck, ik, res from quintuplets "
+ "where rand = ? and autn = ? and id = ? order by use limit 1",
+ DB_BLOB, chunk_create(rand, AKA_RAND_LEN),
+ DB_BLOB, chunk_create(autn, AKA_AUTN_LEN), DB_TEXT, buf,
+ DB_BLOB, DB_BLOB, DB_BLOB);
+ if (query)
+ {
+ if (query->enumerate(query, &ck_chunk, &ik_chunk, &res_chunk))
+ {
+ if (ck_chunk.len == AKA_CK_LEN &&
+ ik_chunk.len == AKA_IK_LEN &&
+ res_chunk.len <= AKA_RES_MAX)
+ {
+ memcpy(ck, ck_chunk.ptr, AKA_CK_LEN);
+ memcpy(ik, ik_chunk.ptr, AKA_IK_LEN);
+ memcpy(res, res_chunk.ptr, res_chunk.len);
+ *res_len = res_chunk.len;
+ found = SUCCESS;
+ }
+ }
+ query->destroy(query);
+ }
+ if (found == SUCCESS)
+ {
+ if (this->remove_used)
+ {
+ this->db->execute(this->db, NULL,
+ "delete from quintuplets where id = ? and rand = ?",
+ DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ else
+ {
+ this->db->execute(this->db, NULL,
+ "update quintuplets set use = ? where id = ? and rand = ?",
+ DB_UINT, time(NULL), DB_TEXT, buf,
+ DB_BLOB, chunk_create(rand, AKA_RAND_LEN));
+ }
+ }
+ return found;
+}
+
+METHOD(eap_simaka_sql_card_t, destroy, void,
+ private_eap_simaka_sql_card_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db,
+ bool remove_used)
+{
+ private_eap_simaka_sql_card_t *this;
+
+ INIT(this,
+ .public = {
+ .card = {
+ .get_triplet = _get_triplet,
+ .get_quintuplet = _get_quintuplet,
+ .resync = (void*)return_false,
+ .get_pseudonym = (void*)return_null,
+ .set_pseudonym = (void*)nop,
+ .get_reauth = (void*)return_null,
+ .set_reauth = (void*)nop,
+ },
+ .destroy = _destroy,
+ },
+ .db = db,
+ .remove_used = remove_used,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h
new file mode 100644
index 000000000..46b7de25e
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql_card eap_simaka_sql_card
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_CARD_H_
+#define EAP_SIMAKA_SQL_CARD_H_
+
+#include <database/database.h>
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_sql_card_t eap_simaka_sql_card_t;
+
+/**
+ * SIM card implementation using a triplet/quintuplet database backend.
+ */
+struct eap_simaka_sql_card_t {
+
+ /**
+ * Implements sim_card_t interface
+ */
+ sim_card_t card;
+
+ /**
+ * Destroy a eap_simaka_sql_card_t.
+ */
+ void (*destroy)(eap_simaka_sql_card_t *this);
+};
+
+/**
+ * Create a eap_simaka_sql_card instance.
+ *
+ * @param db triplet/quintuplet database
+ * @param remove_used TRUE to remove used triplets/quintuplets from db
+ */
+eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db,
+ bool remove_used);
+
+#endif /** EAP_SIMAKA_SQL_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
new file mode 100644
index 000000000..0f5319792
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_plugin.h"
+#include "eap_simaka_sql_card.h"
+#include "eap_simaka_sql_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_t private_eap_simaka_sql_t;
+
+/**
+ * Private data of an eap_simaka_sql_t object.
+ */
+struct private_eap_simaka_sql_t {
+
+ /**
+ * Public eap_simaka_sql_plugin_t interface.
+ */
+ eap_simaka_sql_plugin_t public;
+
+ /**
+ * (U)SIM card
+ */
+ eap_simaka_sql_card_t *card;
+
+ /**
+ * (U)SIM provider
+ */
+ eap_simaka_sql_provider_t *provider;
+
+ /**
+ * Database with triplets/quintuplets
+ */
+ database_t *db;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_eap_simaka_sql_t *this)
+{
+ charon->sim->remove_card(charon->sim, &this->card->card);
+ charon->sim->remove_provider(charon->sim, &this->provider->provider);
+ this->card->destroy(this->card);
+ this->provider->destroy(this->provider);
+ this->db->destroy(this->db);
+ free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_simaka_sql_plugin_create()
+{
+ private_eap_simaka_sql_t *this;
+ database_t *db;
+ bool remove_used;
+ char *uri;
+
+ uri = lib->settings->get_str(lib->settings,
+ "charon.plugins.eap-simaka-sql.database", NULL);
+ if (!uri)
+ {
+ DBG1(DBG_CFG, "eap-simaka-sql database URI missing");
+ return NULL;
+ }
+ db = lib->db->create(lib->db, uri);
+ if (!db)
+ {
+ DBG1(DBG_CFG, "opening eap-simaka-sql database failed");
+ return NULL;
+ }
+ remove_used = lib->settings->get_bool(lib->settings,
+ "charon.plugins.eap-simaka-sql.remove_used", FALSE);
+
+ INIT(this,
+ .public.plugin = {
+ .destroy = _destroy,
+ },
+ .db = db,
+ .provider = eap_simaka_sql_provider_create(db, remove_used),
+ .card = eap_simaka_sql_card_create(db, remove_used),
+ );
+
+ charon->sim->add_card(charon->sim, &this->card->card);
+ charon->sim->add_provider(charon->sim, &this->provider->provider);
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h
new file mode 100644
index 000000000..3064580bf
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql eap_simaka_sql
+ * @ingroup cplugins
+ *
+ * @defgroup eap_simaka_sql_plugin eap_simaka_sql_plugin
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_PLUGIN_H_
+#define EAP_SIMAKA_SQL_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_simaka_sql_plugin_t eap_simaka_sql_plugin_t;
+
+/**
+ * Plugin to provide SIM/AKA cards/providers using triplets from a database.
+ */
+struct eap_simaka_sql_plugin_t {
+
+ /**
+ * Implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** EAP_SIMAKA_SQL_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c
new file mode 100644
index 000000000..73cccf549
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_provider.h"
+
+#include <time.h>
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_provider_t private_eap_simaka_sql_provider_t;
+
+/**
+ * Private data of an eap_simaka_sql_provider_t object.
+ */
+struct private_eap_simaka_sql_provider_t {
+
+ /**
+ * Public eap_simaka_sql_provider_t interface.
+ */
+ eap_simaka_sql_provider_t public;
+
+ /**
+ * Triplet/quintuplet database
+ */
+ database_t *db;
+
+ /**
+ * Remove used triplets/quintuplets from database
+ */
+ bool remove_used;
+};
+
+METHOD(sim_provider_t, get_triplet, bool,
+ private_eap_simaka_sql_provider_t *this, identification_t *id,
+ char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
+{
+ chunk_t rand_chunk, sres_chunk, kc_chunk;
+ enumerator_t *query;
+ bool found = FALSE;
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%Y", id);
+ query = this->db->query(this->db,
+ "select rand, sres, kc from triplets where id = ? order by use",
+ DB_TEXT, buf, DB_BLOB, DB_BLOB, DB_BLOB);
+ if (query)
+ {
+ if (query->enumerate(query, &rand_chunk, &sres_chunk, &kc_chunk))
+ {
+ if (rand_chunk.len == SIM_RAND_LEN &&
+ sres_chunk.len == SIM_SRES_LEN &&
+ kc_chunk.len == SIM_KC_LEN)
+ {
+ memcpy(rand, rand_chunk.ptr, SIM_RAND_LEN);
+ memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN);
+ memcpy(kc, kc_chunk.ptr, SIM_KC_LEN);
+ found = TRUE;
+ }
+ }
+ query->destroy(query);
+ }
+ if (found)
+ {
+ if (this->remove_used)
+ {
+ this->db->execute(this->db, NULL,
+ "delete from triplets where id = ? and rand = ?",
+ DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ else
+ {
+ this->db->execute(this->db, NULL,
+ "update triplets set use = ? where id = ? and rand = ?",
+ DB_UINT, time(NULL), DB_TEXT, buf,
+ DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ }
+ return found;
+}
+
+METHOD(sim_provider_t, get_quintuplet, bool,
+ private_eap_simaka_sql_provider_t *this, identification_t *id,
+ char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len,
+ char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
+{
+ chunk_t rand_chunk, xres_chunk, ck_chunk, ik_chunk, autn_chunk;
+ enumerator_t *query;
+ bool found = FALSE;
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%Y", id);
+ query = this->db->query(this->db, "select rand, res, ck, ik, autn "
+ "from quintuplets where id = ? order by use", DB_TEXT, buf,
+ DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB);
+ if (query)
+ {
+ if (query->enumerate(query, &rand_chunk, &xres_chunk,
+ &ck_chunk, &ik_chunk, &autn_chunk))
+ {
+ if (rand_chunk.len == AKA_RAND_LEN &&
+ xres_chunk.len <= AKA_RES_MAX &&
+ ck_chunk.len == AKA_CK_LEN &&
+ ik_chunk.len == AKA_IK_LEN &&
+ autn_chunk.len == AKA_AUTN_LEN)
+ {
+ memcpy(rand, rand_chunk.ptr, AKA_RAND_LEN);
+ memcpy(xres, xres_chunk.ptr, xres_chunk.len);
+ *xres_len = xres_chunk.len;
+ memcpy(ck, ck_chunk.ptr, AKA_CK_LEN);
+ memcpy(ik, ik_chunk.ptr, AKA_IK_LEN);
+ memcpy(autn, autn_chunk.ptr, AKA_AUTN_LEN);
+ found = TRUE;
+ }
+ }
+ query->destroy(query);
+ }
+ if (found)
+ {
+ if (this->remove_used)
+ {
+ this->db->execute(this->db, NULL,
+ "delete from quintuplets where id = ? and rand = ?",
+ DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+ }
+ else
+ {
+ this->db->execute(this->db, NULL,
+ "update quintuplets set use = ? where id = ? and rand = ?",
+ DB_UINT, time(NULL), DB_TEXT, buf,
+ DB_BLOB, chunk_create(rand, AKA_RAND_LEN));
+ }
+ }
+ return found;
+}
+
+METHOD(eap_simaka_sql_provider_t, destroy, void,
+ private_eap_simaka_sql_provider_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db,
+ bool remove_used)
+{
+ private_eap_simaka_sql_provider_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .get_triplet = _get_triplet,
+ .get_quintuplet = _get_quintuplet,
+ .resync = (void*)return_false,
+ .is_pseudonym = (void*)return_null,
+ .gen_pseudonym = (void*)return_null,
+ .is_reauth = (void*)return_null,
+ .gen_reauth = (void*)return_null,
+ },
+ .destroy = _destroy,
+ },
+ .db = db,
+ .remove_used = remove_used,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h
new file mode 100644
index 000000000..ecb0c8cb0
--- /dev/null
+++ b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql_provider eap_simaka_sql_provider
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_PROVIDER_H_
+#define EAP_SIMAKA_SQL_PROVIDER_H_
+
+#include <database/database.h>
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_sql_provider_t eap_simaka_sql_provider_t;
+
+/**
+ * SIM provider implementation using a triplet/quintuplet database backend.
+ */
+struct eap_simaka_sql_provider_t {
+
+ /**
+ * Implements sim_provider_t interface
+ */
+ sim_provider_t provider;
+
+ /**
+ * Destroy a eap_simaka_sql_provider_t.
+ */
+ void (*destroy)(eap_simaka_sql_provider_t *this);
+};
+
+/**
+ * Create a eap_simaka_sql_provider instance.
+ *
+ * @param db triplet/quintuplet database
+ * @param remove_used TRUE to remove used triplets/quintuplets from db
+ */
+eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db,
+ bool remove_used);
+
+#endif /** EAP_SIMAKA_SQL_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 20ac77080..47952b99e 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/farp/farp_spoofer.c b/src/libcharon/plugins/farp/farp_spoofer.c
index 29e64e32d..20bb44fd3 100644
--- a/src/libcharon/plugins/farp/farp_spoofer.c
+++ b/src/libcharon/plugins/farp/farp_spoofer.c
@@ -156,8 +156,8 @@ farp_spoofer_t *farp_spoofer_create(farp_listener_t *listener)
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, offsetof(arp_t, opcode)),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARPOP_REQUEST, 0, 3),
BPF_STMT(BPF_LD+BPF_W+BPF_LEN, 0),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 28, 0, 1),
- BPF_STMT(BPF_RET+BPF_A, 0),
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, sizeof(arp_t), 0, 1),
+ BPF_STMT(BPF_RET+BPF_K, sizeof(arp_t)),
BPF_STMT(BPF_RET+BPF_K, 0),
};
struct sock_fprog arp_request_filter = {
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am
index 74fe1f4c7..0df1b8d91 100644
--- a/src/libcharon/plugins/ha/Makefile.am
+++ b/src/libcharon/plugins/ha/Makefile.am
@@ -17,9 +17,11 @@ libstrongswan_ha_la_SOURCES = \
ha_tunnel.h ha_tunnel.c \
ha_dispatcher.h ha_dispatcher.c \
ha_segments.h ha_segments.c \
+ ha_cache.h ha_cache.c \
ha_kernel.h ha_kernel.c \
ha_ctl.h ha_ctl.c \
ha_ike.h ha_ike.c \
- ha_child.h ha_child.c
+ ha_child.h ha_child.c \
+ ha_attribute.h ha_attribute.c
libstrongswan_ha_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index c60d3bf56..5ca9b464b 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -76,7 +76,8 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
libstrongswan_ha_la_LIBADD =
am_libstrongswan_ha_la_OBJECTS = ha_plugin.lo ha_message.lo \
ha_socket.lo ha_tunnel.lo ha_dispatcher.lo ha_segments.lo \
- ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo
+ ha_cache.lo ha_kernel.lo ha_ctl.lo ha_ike.lo ha_child.lo \
+ ha_attribute.lo
libstrongswan_ha_la_OBJECTS = $(am_libstrongswan_ha_la_OBJECTS)
libstrongswan_ha_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -269,10 +270,12 @@ libstrongswan_ha_la_SOURCES = \
ha_tunnel.h ha_tunnel.c \
ha_dispatcher.h ha_dispatcher.c \
ha_segments.h ha_segments.c \
+ ha_cache.h ha_cache.c \
ha_kernel.h ha_kernel.c \
ha_ctl.h ha_ctl.c \
ha_ike.h ha_ike.c \
- ha_child.h ha_child.c
+ ha_child.h ha_child.c \
+ ha_attribute.h ha_attribute.c
libstrongswan_ha_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -358,6 +361,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_child.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_ctl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_dispatcher.Plo@am__quote@
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
new file mode 100644
index 000000000..b08abe1a9
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ha_attribute.h"
+
+#include <utils/linked_list.h>
+#include <threading/mutex.h>
+
+typedef struct private_ha_attribute_t private_ha_attribute_t;
+
+/**
+ * Private data of an ha_attribute_t object.
+ */
+struct private_ha_attribute_t {
+
+ /**
+ * Public ha_attribute_t interface.
+ */
+ ha_attribute_t public;
+
+ /**
+ * List of pools, pool_t
+ */
+ linked_list_t *pools;
+
+ /**
+ * Mutex to lock mask
+ */
+ mutex_t *mutex;
+
+ /**
+ * Kernel helper
+ */
+ ha_kernel_t *kernel;
+
+ /**
+ * Segment responsibility
+ */
+ ha_segments_t *segments;
+};
+
+/**
+ * In-memory pool.
+ */
+typedef struct {
+ /** name of the pool */
+ char *name;
+ /** base address of pool */
+ host_t *base;
+ /** total number of addresses in this pool */
+ int size;
+ /** bitmask for address usage */
+ u_char *mask;
+} pool_t;
+
+/**
+ * Clean up a pool entry
+ */
+static void pool_destroy(pool_t *pool)
+{
+ pool->base->destroy(pool->base);
+ free(pool->name);
+ free(pool->mask);
+ free(pool);
+}
+
+/**
+ * convert a pool offset to an address
+ */
+static host_t* offset2host(pool_t *pool, int offset)
+{
+ chunk_t addr;
+ host_t *host;
+ u_int32_t *pos;
+
+ if (offset > pool->size)
+ {
+ return NULL;
+ }
+
+ addr = chunk_clone(pool->base->get_address(pool->base));
+ if (pool->base->get_family(pool->base) == AF_INET6)
+ {
+ pos = (u_int32_t*)(addr.ptr + 12);
+ }
+ else
+ {
+ pos = (u_int32_t*)addr.ptr;
+ }
+ *pos = htonl(offset + ntohl(*pos));
+ host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0);
+ free(addr.ptr);
+ return host;
+}
+
+/**
+ * convert a host to a pool offset
+ */
+static int host2offset(pool_t *pool, host_t *addr)
+{
+ chunk_t host, base;
+ u_int32_t hosti, basei;
+
+ if (addr->get_family(addr) != pool->base->get_family(pool->base))
+ {
+ return -1;
+ }
+ host = addr->get_address(addr);
+ base = pool->base->get_address(pool->base);
+ if (addr->get_family(addr) == AF_INET6)
+ {
+ /* only look at last /32 block */
+ if (!memeq(host.ptr, base.ptr, 12))
+ {
+ return -1;
+ }
+ host = chunk_skip(host, 12);
+ base = chunk_skip(base, 12);
+ }
+ hosti = ntohl(*(u_int32_t*)(host.ptr));
+ basei = ntohl(*(u_int32_t*)(base.ptr));
+ if (hosti > basei + pool->size)
+ {
+ return -1;
+ }
+ return hosti - basei;
+}
+
+/**
+ * Find a pool by its name
+ */
+static pool_t* get_pool(private_ha_attribute_t *this, char *name)
+{
+ enumerator_t *enumerator;
+ pool_t *pool, *found = NULL;
+
+ enumerator = this->pools->create_enumerator(this->pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (streq(name, pool->name))
+ {
+ found = pool;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * Check if we are responsible for a bit in our bitmask
+ */
+static bool responsible_for(private_ha_attribute_t *this, int bit)
+{
+ u_int segment;
+
+ segment = this->kernel->get_segment_int(this->kernel, bit);
+ return this->segments->is_active(this->segments, segment);
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+ private_ha_attribute_t *this, char *name, identification_t *id,
+ host_t *requested)
+{
+ pool_t *pool;
+ int offset = -1, byte, bit;
+ host_t *address;
+
+ this->mutex->lock(this->mutex);
+ pool = get_pool(this, name);
+ if (pool)
+ {
+ for (byte = 0; byte < pool->size / 8; byte++)
+ {
+ if (pool->mask[byte] != 0xFF)
+ {
+ for (bit = 0; bit < 8; bit++)
+ {
+ if (!(pool->mask[byte] & 1 << bit) &&
+ responsible_for(this, bit))
+ {
+ offset = byte * 8 + bit;
+ pool->mask[byte] |= 1 << bit;
+ break;
+ }
+ }
+ }
+ if (offset != -1)
+ {
+ break;
+ }
+ }
+ if (offset == -1)
+ {
+ DBG1(DBG_CFG, "no address left in HA pool '%s' belonging to"
+ "a responsible segment", name);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ if (offset != -1)
+ {
+ address = offset2host(pool, offset);
+ DBG1(DBG_CFG, "acquired address %H from HA pool '%s'", address, name);
+ return address;
+ }
+ return NULL;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+ private_ha_attribute_t *this, char *name, host_t *address,
+ identification_t *id)
+{
+ pool_t *pool;
+ int offset;
+ bool found = FALSE;
+
+ this->mutex->lock(this->mutex);
+ pool = get_pool(this, name);
+ if (pool)
+ {
+ offset = host2offset(pool, address);
+ if (offset > 0 && offset < pool->size)
+ {
+ pool->mask[offset / 8] &= ~(1 << (offset % 8));
+ DBG1(DBG_CFG, "released address %H to HA pool '%s'", address, name);
+ found = TRUE;
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ return found;
+}
+
+METHOD(ha_attribute_t, reserve, void,
+ private_ha_attribute_t *this, char *name, host_t *address)
+{
+ pool_t *pool;
+ int offset;
+
+ this->mutex->lock(this->mutex);
+ pool = get_pool(this, name);
+ if (pool)
+ {
+ offset = host2offset(pool, address);
+ if (offset > 0 && offset < pool->size)
+ {
+ pool->mask[offset / 8] |= 1 << (offset % 8);
+ DBG1(DBG_CFG, "reserved address %H in HA pool '%s'", address, name);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(ha_attribute_t, destroy, void,
+ private_ha_attribute_t *this)
+{
+ this->pools->destroy_function(this->pools, (void*)pool_destroy);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * Load the configured pools.
+ */
+static void load_pools(private_ha_attribute_t *this)
+{
+ enumerator_t *enumerator;
+ char *name, *net, *bits;
+ host_t *base;
+ int mask, maxbits;
+ pool_t *pool;
+
+ enumerator = lib->settings->create_key_value_enumerator(lib->settings,
+ "charon.plugins.ha.pools");
+ while (enumerator->enumerate(enumerator, &name, &net))
+ {
+ net = strdup(net);
+ bits = strchr(net, '/');
+ if (!bits)
+ {
+ DBG1(DBG_CFG, "invalid HA pool '%s' subnet, skipped", name);
+ free(net);
+ continue;
+ }
+ *bits++ = '\0';
+
+ base = host_create_from_string(net, 0);
+ mask = atoi(bits);
+ free(net);
+ if (!base || !mask)
+ {
+ DESTROY_IF(base);
+ DBG1(DBG_CFG, "invalid HA pool '%s', skipped", name);
+ continue;
+ }
+ maxbits = base->get_family(base) == AF_INET ? 32 : 128;
+ mask = maxbits - mask;
+ if (mask > 24)
+ {
+ mask = 24;
+ DBG1(DBG_CFG, "size of HA pool '%s' limited to /%d",
+ name, maxbits - mask);
+ }
+ if (mask < 3)
+ {
+ DBG1(DBG_CFG, "HA pool '%s' too small, skipped", name);
+ base->destroy(base);
+ continue;
+ }
+
+ INIT(pool,
+ .name = strdup(name),
+ .base = base,
+ .size = (1 << mask),
+ );
+ pool->mask = calloc(pool->size / 8, 1);
+ /* do not use first/last address of pool */
+ pool->mask[0] |= 0x01;
+ pool->mask[pool->size / 8 - 1] |= 0x80;
+
+ DBG1(DBG_CFG, "loaded HA pool '%s' %H/%d (%d addresses)",
+ pool->name, pool->base, maxbits - mask, pool->size - 2);
+ this->pools->insert_last(this->pools, pool);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * See header
+ */
+ha_attribute_t *ha_attribute_create(ha_kernel_t *kernel, ha_segments_t *segments)
+{
+ private_ha_attribute_t *this;
+
+ INIT(this,
+ .public = {
+ .provider = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_attribute_enumerator = enumerator_create_empty,
+ },
+ .reserve = _reserve,
+ .destroy = _destroy,
+ },
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .pools = linked_list_create(),
+ .kernel = kernel,
+ .segments = segments,
+ );
+
+ load_pools(this);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/ha/ha_attribute.h b/src/libcharon/plugins/ha/ha_attribute.h
new file mode 100644
index 000000000..d1e4f5e89
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_attribute.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ha_attribute ha_attribute
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_ATTRIBUTE_H_
+#define HA_ATTRIBUTE_H_
+
+#include "ha_kernel.h"
+#include "ha_segments.h"
+
+#include <attributes/attribute_provider.h>
+
+typedef struct ha_attribute_t ha_attribute_t;
+
+/**
+ * A HA enabled in memory address pool attribute provider.
+ */
+struct ha_attribute_t {
+
+ /**
+ * Implements attribute provider interface.
+ */
+ attribute_provider_t provider;
+
+ /**
+ * Reserve an address for a passive IKE_SA.
+ *
+ * @param name pool name to reserve address in
+ * @param address address to reserve
+ */
+ void (*reserve)(ha_attribute_t *this, char *name, host_t *address);
+
+ /**
+ * Destroy a ha_attribute_t.
+ */
+ void (*destroy)(ha_attribute_t *this);
+};
+
+/**
+ * Create a ha_attribute instance.
+ */
+ha_attribute_t *ha_attribute_create(ha_kernel_t *kernel, ha_segments_t *segments);
+
+#endif /** HA_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c
new file mode 100644
index 000000000..1ebc33ca4
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_cache.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ha_cache.h"
+
+#include <utils/hashtable.h>
+#include <utils/linked_list.h>
+#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ha_cache_t private_ha_cache_t;
+
+/**
+ * Private data of an ha_cache_t object.
+ */
+struct private_ha_cache_t {
+
+ /**
+ * Public ha_cache_t interface.
+ */
+ ha_cache_t public;
+
+ /**
+ * Kernel helper functions
+ */
+ ha_kernel_t *kernel;
+
+ /**
+ * Socket to send sync messages over
+ */
+ ha_socket_t *socket;
+
+ /**
+ * Total number of segments
+ */
+ u_int count;
+
+ /**
+ * cached entries (ike_sa_t, entry_t)
+ */
+ hashtable_t *cache;
+
+ /**
+ * Mutex to lock cache
+ */
+ mutex_t *mutex;
+};
+
+/**
+ * Hashtable hash function
+ */
+static u_int hash(void *key)
+{
+ return (uintptr_t)key;
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(void *a, void *b)
+{
+ return a == b;
+}
+
+/**
+ * Cache entry for an IKE_SA
+ */
+typedef struct {
+ /* segment this entry is associate to */
+ u_int segment;
+ /* ADD message */
+ ha_message_t *add;
+ /* list of updates UPDATE message */
+ linked_list_t *updates;
+ /* last initiator mid */
+ ha_message_t *midi;
+ /* last responder mid */
+ ha_message_t *midr;
+} entry_t;
+
+/**
+ * Create a entry with an add message
+ */
+static entry_t *entry_create(ha_message_t *add)
+{
+ entry_t *entry;
+
+ INIT(entry,
+ .add = add,
+ .updates = linked_list_create(),
+ );
+ return entry;
+}
+
+/**
+ * clean up a entry
+ */
+static void entry_destroy(entry_t *entry)
+{
+ entry->updates->destroy_offset(entry->updates,
+ offsetof(ha_message_t, destroy));
+ entry->add->destroy(entry->add);
+ DESTROY_IF(entry->midi);
+ DESTROY_IF(entry->midr);
+ free(entry);
+}
+
+METHOD(ha_cache_t, cache, void,
+ private_ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message)
+{
+ entry_t *entry;
+
+ this->mutex->lock(this->mutex);
+ switch (message->get_type(message))
+ {
+ case HA_IKE_ADD:
+ entry = entry_create(message);
+ entry = this->cache->put(this->cache, ike_sa, entry);
+ if (entry)
+ {
+ entry_destroy(entry);
+ }
+ break;
+ case HA_IKE_UPDATE:
+ entry = this->cache->get(this->cache, ike_sa);
+ if (entry)
+ {
+ entry->segment = this->kernel->get_segment(this->kernel,
+ ike_sa->get_other_host(ike_sa));
+ entry->updates->insert_last(entry->updates, message);
+ break;
+ }
+ message->destroy(message);
+ break;
+ case HA_IKE_MID_INITIATOR:
+ entry = this->cache->get(this->cache, ike_sa);
+ if (entry)
+ {
+ DESTROY_IF(entry->midi);
+ entry->midi = message;
+ break;
+ }
+ message->destroy(message);
+ break;
+ case HA_IKE_MID_RESPONDER:
+ entry = this->cache->get(this->cache, ike_sa);
+ if (entry)
+ {
+ DESTROY_IF(entry->midr);
+ entry->midr = message;
+ break;
+ }
+ message->destroy(message);
+ break;
+ case HA_IKE_DELETE:
+ entry = this->cache->remove(this->cache, ike_sa);
+ if (entry)
+ {
+ entry_destroy(entry);
+ }
+ message->destroy(message);
+ break;
+ default:
+ message->destroy(message);
+ break;
+ }
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(ha_cache_t, delete_, void,
+ private_ha_cache_t *this, ike_sa_t *ike_sa)
+{
+ entry_t *entry;
+
+ entry = this->cache->remove(this->cache, ike_sa);
+ if (entry)
+ {
+ entry_destroy(entry);
+ }
+}
+
+/**
+ * Rekey all children of an IKE_SA
+ */
+static status_t rekey_children(ike_sa_t *ike_sa)
+{
+ iterator_t *iterator;
+ child_sa_t *child_sa;
+ status_t status = SUCCESS;
+
+ iterator = ike_sa->create_child_sa_iterator(ike_sa);
+ while (iterator->iterate(iterator, (void**)&child_sa))
+ {
+ DBG1(DBG_CFG, "resyncing CHILD_SA");
+ status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
+ child_sa->get_spi(child_sa, TRUE));
+ if (status == DESTROY_ME)
+ {
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+ return status;
+}
+
+/**
+ * Trigger rekeying of CHILD_SA in segment
+ */
+static void rekey_segment(private_ha_cache_t *this, u_int segment)
+{
+ ike_sa_t *ike_sa;
+ enumerator_t *enumerator;
+ linked_list_t *list;
+ ike_sa_id_t *id;
+
+ list = linked_list_create();
+
+ enumerator = charon->ike_sa_manager->create_enumerator(
+ charon->ike_sa_manager);
+ while (enumerator->enumerate(enumerator, &ike_sa))
+ {
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ this->kernel->get_segment(this->kernel,
+ ike_sa->get_other_host(ike_sa)) == segment)
+ {
+ id = ike_sa->get_id(ike_sa);
+ list->insert_last(list, id->clone(id));
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ while (list->remove_last(list, (void**)&id) == SUCCESS)
+ {
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
+ if (ike_sa)
+ {
+ if (rekey_children(ike_sa) != DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ }
+ id->destroy(id);
+ }
+ list->destroy(list);
+}
+
+METHOD(ha_cache_t, resync, void,
+ private_ha_cache_t *this, u_int segment)
+{
+ enumerator_t *enumerator, *updates;
+ ike_sa_t *ike_sa;
+ entry_t *entry;
+ ha_message_t *message;
+
+ DBG1(DBG_CFG, "resyncing HA segment %d", segment);
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->cache->create_enumerator(this->cache);
+ while (enumerator->enumerate(enumerator, &ike_sa, &entry))
+ {
+ if (entry->segment == segment)
+ {
+ this->socket->push(this->socket, entry->add);
+ updates = entry->updates->create_enumerator(entry->updates);
+ while (updates->enumerate(updates, &message))
+ {
+ this->socket->push(this->socket, message);
+ }
+ updates->destroy(updates);
+ if (entry->midi)
+ {
+ this->socket->push(this->socket, entry->midi);
+ }
+ if (entry->midr)
+ {
+ this->socket->push(this->socket, entry->midr);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ rekey_segment(this, segment);
+}
+
+/**
+ * Request a resync of all segments
+ */
+static job_requeue_t request_resync(private_ha_cache_t *this)
+{
+ ha_message_t *message;
+ int i;
+
+ DBG1(DBG_CFG, "requesting HA resynchronization");
+
+ message = ha_message_create(HA_RESYNC);
+ for (i = 1; i <= this->count; i++)
+ {
+ message->add_attribute(message, HA_SEGMENT, i);
+ }
+ this->socket->push(this->socket, message);
+ message->destroy(message);
+ return JOB_REQUEUE_NONE;
+}
+
+METHOD(ha_cache_t, destroy, void,
+ private_ha_cache_t *this)
+{
+ this->cache->destroy(this->cache);
+ this->mutex->destroy(this->mutex);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
+ bool sync, u_int count)
+{
+ private_ha_cache_t *this;
+
+ INIT(this,
+ .public = {
+ .cache = _cache,
+ .delete = _delete_,
+ .resync = _resync,
+ .destroy = _destroy,
+ },
+ .count = count,
+ .kernel = kernel,
+ .socket = socket,
+ .cache = hashtable_create(hash, equals, 8),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ if (sync)
+ {
+ /* request a resync as soon as we are up */
+ charon->scheduler->schedule_job(charon->scheduler, (job_t*)
+ callback_job_create((callback_job_cb_t)request_resync,
+ this, NULL, NULL), 1);
+ }
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/ha/ha_cache.h b/src/libcharon/plugins/ha/ha_cache.h
new file mode 100644
index 000000000..39f1947a8
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_cache.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup ha_cache ha_cache
+ * @{ @ingroup ha
+ */
+
+#ifndef HA_CACHE_H_
+#define HA_CACHE_H_
+
+typedef struct ha_cache_t ha_cache_t;
+
+#include "ha_message.h"
+#include "ha_kernel.h"
+#include "ha_socket.h"
+
+#include <utils/enumerator.h>
+
+#include <sa/ike_sa.h>
+
+/**
+ * HA message caching facility, allows reintegration of new nodes.
+ */
+struct ha_cache_t {
+
+ /**
+ * Cache an IKE specific message.
+ *
+ * @param ike_sa associated IKE_SA
+ * @param message message to cache
+ */
+ void (*cache)(ha_cache_t *this, ike_sa_t *ike_sa, ha_message_t *message);
+
+ /**
+ * Delete a cache entry for an IKE_SA.
+ *
+ * @param ike_sa cache entry to delete
+ */
+ void (*delete)(ha_cache_t *this, ike_sa_t *ike_sa);
+
+ /**
+ * Resync a segment to the node using the cached messages.
+ *
+ * @param segment segment to resync
+ */
+ void (*resync)(ha_cache_t *this, u_int segment);
+
+ /**
+ * Destroy a ha_cache_t.
+ */
+ void (*destroy)(ha_cache_t *this);
+};
+
+/**
+ * Create a ha_cache instance.
+ *
+ * @param kernel kernel helper
+ * @param socket socket to send resync messages
+ * @param resync request a resync during startup?
+ * @param count total number of segments
+ */
+ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
+ bool resync, u_int count);
+
+#endif /** HA_CACHE_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c
index 2eb8e27f6..1a9425423 100644
--- a/src/libcharon/plugins/ha/ha_child.c
+++ b/src/libcharon/plugins/ha/ha_child.c
@@ -36,22 +36,30 @@ struct private_ha_child_t {
* tunnel securing sync messages
*/
ha_tunnel_t *tunnel;
+
+ /**
+ * Segment handling
+ */
+ ha_segments_t *segments;
+
+ /**
+ * Kernel helper
+ */
+ ha_kernel_t *kernel;
};
-/**
- * Implementation of listener_t.child_keys
- */
-static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa,
- child_sa_t *child_sa, diffie_hellman_t *dh,
- chunk_t nonce_i, chunk_t nonce_r)
+METHOD(listener_t, child_keys, bool,
+ private_ha_child_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ bool initiator, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
{
ha_message_t *m;
chunk_t secret;
proposal_t *proposal;
u_int16_t alg, len;
- linked_list_t *list;
+ linked_list_t *local_ts, *remote_ts;
enumerator_t *enumerator;
traffic_selector_t *ts;
+ u_int seg_i, seg_o;
if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
{ /* do not sync SA between nodes */
@@ -61,6 +69,7 @@ static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa,
m = ha_message_create(HA_CHILD_ADD);
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_INITIATOR, (u_int8_t)initiator);
m->add_attribute(m, HA_INBOUND_SPI, child_sa->get_spi(child_sa, TRUE));
m->add_attribute(m, HA_OUTBOUND_SPI, child_sa->get_spi(child_sa, FALSE));
m->add_attribute(m, HA_INBOUND_CPI, child_sa->get_cpi(child_sa, TRUE));
@@ -90,31 +99,40 @@ static bool child_keys(private_ha_child_t *this, ike_sa_t *ike_sa,
chunk_clear(&secret);
}
- list = child_sa->get_traffic_selectors(child_sa, TRUE);
- enumerator = list->create_enumerator(list);
+ local_ts = child_sa->get_traffic_selectors(child_sa, TRUE);
+ enumerator = local_ts->create_enumerator(local_ts);
while (enumerator->enumerate(enumerator, &ts))
{
m->add_attribute(m, HA_LOCAL_TS, ts);
}
enumerator->destroy(enumerator);
- list = child_sa->get_traffic_selectors(child_sa, FALSE);
- enumerator = list->create_enumerator(list);
+ remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE);
+ enumerator = remote_ts->create_enumerator(remote_ts);
while (enumerator->enumerate(enumerator, &ts))
{
m->add_attribute(m, HA_REMOTE_TS, ts);
}
enumerator->destroy(enumerator);
+ seg_i = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_my_host(ike_sa), child_sa->get_spi(child_sa, TRUE));
+ seg_o = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_other_host(ike_sa), child_sa->get_spi(child_sa, FALSE));
+ DBG1(DBG_CFG, "handling HA CHILD_SA %s{%d} %#R=== %#R "
+ "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa), local_ts, remote_ts,
+ seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+ seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
+
this->socket->push(this->socket, m);
+ m->destroy(m);
return TRUE;
}
-/**
- * Implementation of listener_t.child_state_change
- */
-static bool child_state_change(private_ha_child_t *this, ike_sa_t *ike_sa,
- child_sa_t *child_sa, child_sa_state_t state)
+METHOD(listener_t, child_state_change, bool,
+ private_ha_child_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_sa_state_t state)
{
if (!ike_sa ||
ike_sa->get_state(ike_sa) == IKE_PASSIVE ||
@@ -138,14 +156,13 @@ static bool child_state_change(private_ha_child_t *this, ike_sa_t *ike_sa,
m->add_attribute(m, HA_INBOUND_SPI,
child_sa->get_spi(child_sa, TRUE));
this->socket->push(this->socket, m);
+ m->destroy(m);
}
return TRUE;
}
-/**
- * Implementation of ha_child_t.destroy.
- */
-static void destroy(private_ha_child_t *this)
+METHOD(ha_child_t, destroy, void,
+ private_ha_child_t *this)
{
free(this);
}
@@ -153,17 +170,24 @@ static void destroy(private_ha_child_t *this)
/**
* See header
*/
-ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
+ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
+ ha_segments_t *segments, ha_kernel_t *kernel)
{
- private_ha_child_t *this = malloc_thing(private_ha_child_t);
-
- memset(&this->public.listener, 0, sizeof(listener_t));
- this->public.listener.child_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, child_sa_t *child_sa, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r))child_keys;
- this->public.listener.child_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, child_sa_t *child_sa, child_sa_state_t state))child_state_change;
- this->public.destroy = (void(*)(ha_child_t*))destroy;
-
- this->socket = socket;
- this->tunnel = tunnel;
+ private_ha_child_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .child_keys = _child_keys,
+ .child_state_change = _child_state_change,
+ },
+ .destroy = _destroy,
+ },
+ .socket = socket,
+ .tunnel = tunnel,
+ .segments = segments,
+ .kernel = kernel,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/ha/ha_child.h b/src/libcharon/plugins/ha/ha_child.h
index ea83495f7..56cd769ba 100644
--- a/src/libcharon/plugins/ha/ha_child.h
+++ b/src/libcharon/plugins/ha/ha_child.h
@@ -21,14 +21,15 @@
#ifndef HA_CHILD_H_
#define HA_CHILD_H_
+typedef struct ha_child_t ha_child_t;
+
#include "ha_socket.h"
#include "ha_tunnel.h"
#include "ha_segments.h"
+#include "ha_kernel.h"
#include <daemon.h>
-typedef struct ha_child_t ha_child_t;
-
/**
* Listener to synchronize CHILD_SAs.
*/
@@ -50,8 +51,11 @@ struct ha_child_t {
*
* @param socket socket to use for sending synchronization messages
* @param tunnel tunnel securing sync messages, if any
+ * @param segments segment handling
+ * @param kernel kernel helper
* @return CHILD listener
*/
-ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
+ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
+ ha_segments_t *segments, ha_kernel_t *kernel);
-#endif /* HA_CHILD_ @}*/
+#endif /** HA_CHILD_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
index 441d26d9e..e188a8484 100644
--- a/src/libcharon/plugins/ha/ha_ctl.c
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -45,6 +45,11 @@ struct private_ha_ctl_t {
ha_segments_t *segments;
/**
+ * Resynchronization message cache
+ */
+ ha_cache_t *cache;
+
+ /**
* FIFO reader thread
*/
callback_job_t *job;
@@ -84,7 +89,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
this->segments->deactivate(this->segments, segment, TRUE);
break;
case '*':
- this->segments->resync(this->segments, segment);
+ this->cache->resync(this->cache, segment);
break;
default:
break;
@@ -96,10 +101,8 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
return JOB_REQUEUE_DIRECT;
}
-/**
- * Implementation of ha_ctl_t.destroy.
- */
-static void destroy(private_ha_ctl_t *this)
+METHOD(ha_ctl_t, destroy, void,
+ private_ha_ctl_t *this)
{
this->job->cancel(this->job);
free(this);
@@ -108,11 +111,17 @@ static void destroy(private_ha_ctl_t *this)
/**
* See header
*/
-ha_ctl_t *ha_ctl_create(ha_segments_t *segments)
+ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
{
- private_ha_ctl_t *this = malloc_thing(private_ha_ctl_t);
+ private_ha_ctl_t *this;
- this->public.destroy = (void(*)(ha_ctl_t*))destroy;
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .segments = segments,
+ .cache = cache,
+ );
if (access(HA_FIFO, R_OK|W_OK) != 0)
{
@@ -123,7 +132,6 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments)
}
}
- this->segments = segments;
this->job = callback_job_create((callback_job_cb_t)dispatch_fifo,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
diff --git a/src/libcharon/plugins/ha/ha_ctl.h b/src/libcharon/plugins/ha/ha_ctl.h
index f33a809be..1e717832a 100644
--- a/src/libcharon/plugins/ha/ha_ctl.h
+++ b/src/libcharon/plugins/ha/ha_ctl.h
@@ -22,6 +22,7 @@
#define HA_CTL_H_
#include "ha_segments.h"
+#include "ha_cache.h"
typedef struct ha_ctl_t ha_ctl_t;
@@ -40,8 +41,9 @@ struct ha_ctl_t {
* Create a ha_ctl instance.
*
* @param segments segments to control
+ * @param cache message cache for resynchronization
* @return HA control interface
*/
-ha_ctl_t *ha_ctl_create(ha_segments_t *segments);
+ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache);
-#endif /* HA_CTL_ @}*/
+#endif /** HA_CTL_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 7df2f1fa8..3bc426ea0 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -41,6 +41,21 @@ struct private_ha_dispatcher_t {
ha_segments_t *segments;
/**
+ * Cache for resync
+ */
+ ha_cache_t *cache;
+
+ /**
+ * Kernel helper
+ */
+ ha_kernel_t *kernel;
+
+ /**
+ * HA enabled pool
+ */
+ ha_attribute_t *attr;
+
+ /**
* Dispatcher job
*/
callback_job_t *job;
@@ -153,6 +168,8 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
old_sa = NULL;
}
ike_sa->set_state(ike_sa, IKE_CONNECTING);
+ this->cache->cache(this->cache, ike_sa, message);
+ message = NULL;
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
else
@@ -167,6 +184,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
}
+ DESTROY_IF(message);
}
/**
@@ -201,6 +219,8 @@ static void process_ike_update(private_ha_dispatcher_t *this,
enumerator_t *enumerator;
ike_sa_t *ike_sa = NULL;
peer_cfg_t *peer_cfg = NULL;
+ auth_cfg_t *auth;
+ bool received_vip = FALSE;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -222,6 +242,11 @@ static void process_ike_update(private_ha_dispatcher_t *this,
case HA_REMOTE_ID:
ike_sa->set_other_id(ike_sa, value.id->clone(value.id));
break;
+ case HA_REMOTE_EAP_ID:
+ auth = auth_cfg_create();
+ auth->add(auth, AUTH_RULE_EAP_IDENTITY, value.id->clone(value.id));
+ ike_sa->add_auth_cfg(ike_sa, FALSE, auth);
+ break;
case HA_LOCAL_ADDR:
ike_sa->set_my_host(ike_sa, value.host->clone(value.host));
break;
@@ -233,6 +258,7 @@ static void process_ike_update(private_ha_dispatcher_t *this,
break;
case HA_REMOTE_VIP:
ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ received_vip = TRUE;
break;
case HA_ADDITIONAL_ADDR:
ike_sa->add_additional_address(ike_sa,
@@ -265,12 +291,6 @@ static void process_ike_update(private_ha_dispatcher_t *this,
set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN);
set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR);
break;
- case HA_INITIATE_MID:
- ike_sa->set_message_id(ike_sa, TRUE, value.u32);
- break;
- case HA_RESPOND_MID:
- ike_sa->set_message_id(ike_sa, FALSE, value.u32);
- break;
default:
break;
}
@@ -282,10 +302,81 @@ static void process_ike_update(private_ha_dispatcher_t *this,
if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
ike_sa->get_peer_cfg(ike_sa))
{
+ DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
+ ike_sa->get_name(ike_sa),
+ ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
+ ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
ike_sa->set_state(ike_sa, IKE_PASSIVE);
}
+ if (received_vip)
+ {
+ host_t *vip;
+ char *pool;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (peer_cfg && vip)
+ {
+ pool = peer_cfg->get_pool(peer_cfg);
+ if (pool)
+ {
+ this->attr->reserve(this->attr, pool, vip);
+ }
+ }
+ }
+ this->cache->cache(this->cache, ike_sa, message);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
+ else
+ {
+ DBG1(DBG_CFG, "passive HA IKE_SA to update not found");
+ message->destroy(message);
+ }
+}
+
+/**
+ * Process messages of type IKE_MID_INITIATOR/RESPONDER
+ */
+static void process_ike_mid(private_ha_dispatcher_t *this,
+ ha_message_t *message, bool initiator)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ u_int32_t mid = 0;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_MID:
+ mid = value.u32;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ if (mid)
+ {
+ ike_sa->set_message_id(ike_sa, initiator, mid);
+ }
+ this->cache->cache(this->cache, ike_sa, message);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ message->destroy(message);
+ }
}
/**
@@ -297,7 +388,7 @@ static void process_ike_delete(private_ha_dispatcher_t *this,
ha_message_attribute_t attribute;
ha_message_value_t value;
enumerator_t *enumerator;
- ike_sa_t *ike_sa;
+ ike_sa_t *ike_sa = NULL;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -307,17 +398,22 @@ static void process_ike_delete(private_ha_dispatcher_t *this,
case HA_IKE_ID:
ike_sa = charon->ike_sa_manager->checkout(
charon->ike_sa_manager, value.ike_sa_id);
- if (ike_sa)
- {
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, ike_sa);
- }
break;
default:
break;
}
}
enumerator->destroy(enumerator);
+ if (ike_sa)
+ {
+ this->cache->cache(this->cache, ike_sa, message);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ message->destroy(message);
+ }
}
/**
@@ -366,6 +462,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
u_int16_t inbound_cpi = 0, outbound_cpi = 0;
u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ u_int seg_i, seg_o;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
chunk_t encr_i, integ_i, encr_r, integ_r;
linked_list_t *local_ts, *remote_ts;
@@ -381,11 +478,13 @@ static void process_child_add(private_ha_dispatcher_t *this,
case HA_IKE_ID:
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
value.ike_sa_id);
- initiator = value.ike_sa_id->is_initiator(value.ike_sa_id);
break;
case HA_CONFIG_NAME:
config_name = value.str;
break;
+ case HA_INITIATOR:
+ initiator = value.u8;
+ break;
case HA_INBOUND_SPI:
inbound_spi = value.u32;
break;
@@ -431,6 +530,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
if (!ike_sa)
{
DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found");
+ message->destroy(message);
return;
}
config = find_child_cfg(ike_sa, config_name);
@@ -438,6 +538,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
{
DBG1(DBG_CHD, "HA is missing nodes child configuration");
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ message->destroy(message);
return;
}
@@ -524,15 +625,27 @@ static void process_child_add(private_ha_dispatcher_t *this,
local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ message->destroy(message);
return;
}
+ seg_i = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_my_host(ike_sa), inbound_spi);
+ seg_o = this->kernel->get_segment_spi(this->kernel,
+ ike_sa->get_other_host(ike_sa), outbound_spi);
+
+ DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R=== %#R "
+ "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
+ child_sa->get_reqid(child_sa), local_ts, remote_ts,
+ seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
+ seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
child_sa->add_policies(child_sa, local_ts, remote_ts);
local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
child_sa->set_state(child_sa, CHILD_INSTALLED);
ike_sa->add_child_sa(ike_sa, child_sa);
+ message->destroy(message);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
@@ -546,6 +659,8 @@ static void process_child_delete(private_ha_dispatcher_t *this,
ha_message_value_t value;
enumerator_t *enumerator;
ike_sa_t *ike_sa = NULL;
+ child_sa_t *child_sa;
+ u_int32_t spi = 0;
enumerator = message->create_attribute_enumerator(message);
while (enumerator->enumerate(enumerator, &attribute, &value))
@@ -557,20 +672,24 @@ static void process_child_delete(private_ha_dispatcher_t *this,
value.ike_sa_id);
break;
case HA_INBOUND_SPI:
- if (ike_sa)
- {
- ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, value.u32);
- }
+ spi = value.u32;
break;
default:
break;
}
}
+ enumerator->destroy(enumerator);
+
if (ike_sa)
{
+ child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE);
+ if (child_sa)
+ {
+ ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi);
+ }
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
- enumerator->destroy(enumerator);
+ message->destroy(message);
}
/**
@@ -605,6 +724,7 @@ static void process_segment(private_ha_dispatcher_t *this,
}
}
enumerator->destroy(enumerator);
+ message->destroy(message);
}
/**
@@ -633,6 +753,7 @@ static void process_status(private_ha_dispatcher_t *this,
enumerator->destroy(enumerator);
this->segments->handle_status(this->segments, mask);
+ message->destroy(message);
}
/**
@@ -651,13 +772,14 @@ static void process_resync(private_ha_dispatcher_t *this,
switch (attribute)
{
case HA_SEGMENT:
- this->segments->resync(this->segments, value.u16);
+ this->cache->resync(this->cache, value.u16);
break;
default:
break;
}
}
enumerator->destroy(enumerator);
+ message->destroy(message);
}
/**
@@ -666,9 +788,16 @@ static void process_resync(private_ha_dispatcher_t *this,
static job_requeue_t dispatch(private_ha_dispatcher_t *this)
{
ha_message_t *message;
+ ha_message_type_t type;
message = this->socket->pull(this->socket);
- switch (message->get_type(message))
+ type = message->get_type(message);
+ if (type != HA_STATUS)
+ {
+ DBG2(DBG_CFG, "received HA %N message", ha_message_type_names,
+ message->get_type(message));
+ }
+ switch (type)
{
case HA_IKE_ADD:
process_ike_add(this, message);
@@ -676,6 +805,12 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
case HA_IKE_UPDATE:
process_ike_update(this, message);
break;
+ case HA_IKE_MID_INITIATOR:
+ process_ike_mid(this, message, TRUE);
+ break;
+ case HA_IKE_MID_RESPONDER:
+ process_ike_mid(this, message, FALSE);
+ break;
case HA_IKE_DELETE:
process_ike_delete(this, message);
break;
@@ -698,19 +833,15 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
process_resync(this, message);
break;
default:
- DBG1(DBG_CFG, "received unknown HA message type %d",
- message->get_type(message));
+ DBG1(DBG_CFG, "received unknown HA message type %d", type);
+ message->destroy(message);
break;
}
- message->destroy(message);
-
return JOB_REQUEUE_DIRECT;
}
-/**
- * Implementation of ha_dispatcher_t.destroy.
- */
-static void destroy(private_ha_dispatcher_t *this)
+METHOD(ha_dispatcher_t, destroy, void,
+ private_ha_dispatcher_t *this)
{
this->job->cancel(this->job);
free(this);
@@ -720,14 +851,22 @@ static void destroy(private_ha_dispatcher_t *this)
* See header
*/
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
- ha_segments_t *segments)
+ ha_segments_t *segments, ha_cache_t *cache,
+ ha_kernel_t *kernel, ha_attribute_t *attr)
{
- private_ha_dispatcher_t *this = malloc_thing(private_ha_dispatcher_t);
-
- this->public.destroy = (void(*)(ha_dispatcher_t*))destroy;
-
- this->socket = socket;
- this->segments = segments;
+ private_ha_dispatcher_t *this;
+
+
+ INIT(this,
+ .public = {
+ .destroy = _destroy,
+ },
+ .socket = socket,
+ .segments = segments,
+ .cache = cache,
+ .kernel = kernel,
+ .attr = attr,
+ );
this->job = callback_job_create((callback_job_cb_t)dispatch,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.h b/src/libcharon/plugins/ha/ha_dispatcher.h
index d2baace3f..105a40473 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.h
+++ b/src/libcharon/plugins/ha/ha_dispatcher.h
@@ -23,6 +23,9 @@
#include "ha_socket.h"
#include "ha_segments.h"
+#include "ha_cache.h"
+#include "ha_kernel.h"
+#include "ha_attribute.h"
typedef struct ha_dispatcher_t ha_dispatcher_t;
@@ -42,9 +45,13 @@ struct ha_dispatcher_t {
*
* @param socket socket to pull messages from
* @param segments segments to control based on received messages
+ * @param cache message cache to use for resynchronization
+ * @param kernel kernel helper
+ * @param attr HA enabled pool
* @return dispatcher object
*/
ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
- ha_segments_t *segments);
+ ha_segments_t *segments, ha_cache_t *cache,
+ ha_kernel_t *kernel, ha_attribute_t *attr);
-#endif /* HA_DISPATCHER_ @}*/
+#endif /** HA_DISPATCHER_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index 1f025d0e5..1efba4e8f 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -36,6 +36,11 @@ struct private_ha_ike_t {
* tunnel securing sync messages
*/
ha_tunnel_t *tunnel;
+
+ /**
+ * message cache
+ */
+ ha_cache_t *cache;
};
/**
@@ -62,12 +67,9 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
return 0;
}
-/**
- * Implementation of listener_t.ike_keys
- */
-static bool ike_keys(private_ha_ike_t *this, ike_sa_t *ike_sa,
- diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
- ike_sa_t *rekey)
+METHOD(listener_t, ike_keys, bool,
+ private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
+ chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey)
{
ha_message_t *m;
chunk_t secret;
@@ -120,14 +122,13 @@ static bool ike_keys(private_ha_ike_t *this, ike_sa_t *ike_sa,
chunk_clear(&secret);
this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
return TRUE;
}
-/**
- * Implementation of listener_t.ike_updown
- */
-static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
+METHOD(listener_t, ike_updown, bool,
+ private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
{
ha_message_t *m;
@@ -147,6 +148,7 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
u_int32_t extension, condition;
host_t *addr;
ike_sa_id_t *id;
+ identification_t *eap_id;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
@@ -168,6 +170,11 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
m->add_attribute(m, HA_IKE_ID, id);
m->add_attribute(m, HA_LOCAL_ID, ike_sa->get_my_id(ike_sa));
m->add_attribute(m, HA_REMOTE_ID, ike_sa->get_other_id(ike_sa));
+ eap_id = ike_sa->get_other_eap_id(ike_sa);
+ if (!eap_id->equals(eap_id, ike_sa->get_other_id(ike_sa)))
+ {
+ m->add_attribute(m, HA_REMOTE_EAP_ID, eap_id);
+ }
m->add_attribute(m, HA_LOCAL_ADDR, ike_sa->get_my_host(ike_sa));
m->add_attribute(m, HA_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
m->add_attribute(m, HA_CONDITIONS, condition);
@@ -186,24 +193,31 @@ static bool ike_updown(private_ha_ike_t *this, ike_sa_t *ike_sa, bool up)
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
}
this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
return TRUE;
}
-/**
- * Implementation of listener_t.ike_rekey
- */
-static bool ike_rekey(private_ha_ike_t *this, ike_sa_t *old, ike_sa_t *new)
+METHOD(listener_t, ike_rekey, bool,
+ private_ha_ike_t *this, ike_sa_t *old, ike_sa_t *new)
{
ike_updown(this, old, FALSE);
ike_updown(this, new, TRUE);
return TRUE;
}
-/**
- * Implementation of listener_t.message
- */
-static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa,
- message_t *message, bool incoming)
+METHOD(listener_t, ike_state_change, bool,
+ private_ha_ike_t *this, ike_sa_t *ike_sa, ike_sa_state_t new)
+{
+ /* delete any remaining cache entry if IKE_SA gets destroyed */
+ if (new == IKE_DESTROYING)
+ {
+ this->cache->delete(this->cache, ike_sa);
+ }
+ return TRUE;
+}
+
+METHOD(listener_t, message_hook, bool,
+ private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming)
{
if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
{ /* do not sync SA between nodes */
@@ -214,20 +228,19 @@ static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa,
message->get_request(message))
{ /* we sync on requests, but skip it on IKE_SA_INIT */
ha_message_t *m;
- u_int32_t mid;
- m = ha_message_create(HA_IKE_UPDATE);
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- mid = message->get_message_id(message) + 1;
if (incoming)
{
- m->add_attribute(m, HA_RESPOND_MID, mid);
+ m = ha_message_create(HA_IKE_MID_RESPONDER);
}
else
{
- m->add_attribute(m, HA_INITIATE_MID, mid);
+ m = ha_message_create(HA_IKE_MID_INITIATOR);
}
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
}
if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
message->get_exchange_type(message) == IKE_AUTH &&
@@ -245,15 +258,14 @@ static bool message_hook(private_ha_ike_t *this, ike_sa_t *ike_sa,
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
m->add_attribute(m, HA_REMOTE_VIP, vip);
this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
}
}
return TRUE;
}
-/**
- * Implementation of ha_ike_t.destroy.
- */
-static void destroy(private_ha_ike_t *this)
+METHOD(ha_ike_t, destroy, void,
+ private_ha_ike_t *this)
{
free(this);
}
@@ -261,19 +273,26 @@ static void destroy(private_ha_ike_t *this)
/**
* See header
*/
-ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel)
+ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
+ ha_cache_t *cache)
{
- private_ha_ike_t *this = malloc_thing(private_ha_ike_t);
-
- memset(&this->public.listener, 0, sizeof(listener_t));
- this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys;
- this->public.listener.ike_updown = (bool(*)(listener_t*,ike_sa_t *ike_sa, bool up))ike_updown;
- this->public.listener.ike_rekey = (bool(*)(listener_t*,ike_sa_t *old, ike_sa_t *new))ike_rekey;
- this->public.listener.message = (bool(*)(listener_t*, ike_sa_t *, message_t *,bool))message_hook;
- this->public.destroy = (void(*)(ha_ike_t*))destroy;
-
- this->socket = socket;
- this->tunnel = tunnel;
+ private_ha_ike_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .ike_keys = _ike_keys,
+ .ike_updown = _ike_updown,
+ .ike_rekey = _ike_rekey,
+ .ike_state_change = _ike_state_change,
+ .message = _message_hook,
+ },
+ .destroy = _destroy,
+ },
+ .socket = socket,
+ .tunnel = tunnel,
+ .cache = cache,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/ha/ha_ike.h b/src/libcharon/plugins/ha/ha_ike.h
index 9de210e67..b22cd6250 100644
--- a/src/libcharon/plugins/ha/ha_ike.h
+++ b/src/libcharon/plugins/ha/ha_ike.h
@@ -21,14 +21,15 @@
#ifndef HA_IKE_H_
#define HA_IKE_H_
+typedef struct ha_ike_t ha_ike_t;
+
#include "ha_socket.h"
#include "ha_tunnel.h"
#include "ha_segments.h"
+#include "ha_cache.h"
#include <daemon.h>
-typedef struct ha_ike_t ha_ike_t;
-
/**
* Listener to synchronize IKE_SAs.
*/
@@ -50,8 +51,10 @@ struct ha_ike_t {
*
* @param socket socket to use for sending synchronization messages
* @param tunnel tunnel securing sync messages, if any
+ * @param cache message cache
* @return IKE listener
*/
-ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel);
+ha_ike_t *ha_ike_create(ha_socket_t *socket, ha_tunnel_t *tunnel,
+ ha_cache_t *cache);
-#endif /* HA_IKE_ @}*/
+#endif /** HA_IKE_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c
index 0ad9c22c3..10a63453a 100644
--- a/src/libcharon/plugins/ha/ha_kernel.c
+++ b/src/libcharon/plugins/ha/ha_kernel.c
@@ -52,24 +52,57 @@ struct private_ha_kernel_t {
};
/**
- * Implementation of ha_kernel_t.in_segment
+ * Segmentate a calculated hash
*/
-static bool in_segment(private_ha_kernel_t *this, host_t *host, u_int segment)
+static u_int hash2segment(private_ha_kernel_t *this, u_int64_t hash)
+{
+ return ((hash * this->count) >> 32) + 1;
+}
+
+/**
+ * Get a host as an integer for hashing
+ */
+static u_int32_t host2int(host_t *host)
{
if (host->get_family(host) == AF_INET)
{
- unsigned long hash;
- u_int32_t addr;
+ return *(u_int32_t*)host->get_address(host).ptr;
+ }
+ return 0;
+}
- addr = *(u_int32_t*)host->get_address(host).ptr;
- hash = jhash_1word(ntohl(addr), this->initval);
+METHOD(ha_kernel_t, get_segment, u_int,
+ private_ha_kernel_t *this, host_t *host)
+{
+ unsigned long hash;
+ u_int32_t addr;
- if ((((u_int64_t)hash * this->count) >> 32) + 1 == segment)
- {
- return TRUE;
- }
- }
- return FALSE;
+ addr = host2int(host);
+ hash = jhash_1word(ntohl(addr), this->initval);
+
+ return hash2segment(this, hash);
+}
+
+METHOD(ha_kernel_t, get_segment_spi, u_int,
+ private_ha_kernel_t *this, host_t *host, u_int32_t spi)
+{
+ unsigned long hash;
+ u_int32_t addr;
+
+ addr = host2int(host);
+ hash = jhash_2words(ntohl(addr), ntohl(spi), this->initval);
+
+ return hash2segment(this, hash);
+}
+
+METHOD(ha_kernel_t, get_segment_int, u_int,
+ private_ha_kernel_t *this, int n)
+{
+ unsigned long hash;
+
+ hash = jhash_1word(ntohl(n), this->initval);
+
+ return hash2segment(this, hash);
}
/**
@@ -142,10 +175,8 @@ static segment_mask_t get_active(private_ha_kernel_t *this, char *file)
return mask;
}
-/**
- * Implementation of ha_kernel_t.activate
- */
-static void activate(private_ha_kernel_t *this, u_int segment)
+METHOD(ha_kernel_t, activate, void,
+ private_ha_kernel_t *this, u_int segment)
{
enumerator_t *enumerator;
char *file;
@@ -158,10 +189,8 @@ static void activate(private_ha_kernel_t *this, u_int segment)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of ha_kernel_t.deactivate
- */
-static void deactivate(private_ha_kernel_t *this, u_int segment)
+METHOD(ha_kernel_t, deactivate, void,
+ private_ha_kernel_t *this, u_int segment)
{
enumerator_t *enumerator;
char *file;
@@ -199,10 +228,8 @@ static void disable_all(private_ha_kernel_t *this)
enumerator->destroy(enumerator);
}
-/**
- * Implementation of ha_kernel_t.destroy.
- */
-static void destroy(private_ha_kernel_t *this)
+METHOD(ha_kernel_t, destroy, void,
+ private_ha_kernel_t *this)
{
free(this);
}
@@ -212,15 +239,20 @@ static void destroy(private_ha_kernel_t *this)
*/
ha_kernel_t *ha_kernel_create(u_int count)
{
- private_ha_kernel_t *this = malloc_thing(private_ha_kernel_t);
-
- this->public.in_segment = (bool(*)(ha_kernel_t*, host_t *host, u_int segment))in_segment;
- this->public.activate = (void(*)(ha_kernel_t*, u_int segment))activate;
- this->public.deactivate = (void(*)(ha_kernel_t*, u_int segment))deactivate;
- this->public.destroy = (void(*)(ha_kernel_t*))destroy;
+ private_ha_kernel_t *this;
- this->initval = 0;
- this->count = count;
+ INIT(this,
+ .public = {
+ .get_segment = _get_segment,
+ .get_segment_spi = _get_segment_spi,
+ .get_segment_int = _get_segment_int,
+ .activate = _activate,
+ .deactivate = _deactivate,
+ .destroy = _destroy,
+ },
+ .initval = 0,
+ .count = count,
+ );
disable_all(this);
diff --git a/src/libcharon/plugins/ha/ha_kernel.h b/src/libcharon/plugins/ha/ha_kernel.h
index b37cc7667..7b56f1e3a 100644
--- a/src/libcharon/plugins/ha/ha_kernel.h
+++ b/src/libcharon/plugins/ha/ha_kernel.h
@@ -31,13 +31,28 @@ typedef struct ha_kernel_t ha_kernel_t;
struct ha_kernel_t {
/**
- * Check if a host is in a segment.
+ * Get the segment a host is in.
*
- * @param host host to check
- * @param segment segment
- * @return TRUE if host belongs to segment
+ * @param host host to get segment for
+ * @return segment number
*/
- bool (*in_segment)(ha_kernel_t *this, host_t *host, u_int segment);
+ u_int (*get_segment)(ha_kernel_t *this, host_t *host);
+
+ /**
+ * Get the segment a host/SPI is in, as used for CHILD_SA segmentation.
+ *
+ * @param host host to get segment for
+ * @param spi SPI to include in hash
+ * @return segment number
+ */
+ u_int (*get_segment_spi)(ha_kernel_t *this, host_t *host, u_int32_t spi);
+
+ /**
+ * Get the segment an arbitrary integer is in.
+ *
+ * @param n integer to segmentate
+ */
+ u_int (*get_segment_int)(ha_kernel_t *this, int n);
/**
* Activate a segment at kernel level for all cluster addresses.
@@ -63,8 +78,7 @@ struct ha_kernel_t {
* Create a ha_kernel instance.
*
* @param count total number of segments to use
- * @param active bitmask of initially active segments
*/
ha_kernel_t *ha_kernel_create(u_int count);
-#endif /* HA_KERNEL_ @}*/
+#endif /** HA_KERNEL_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c
index 54b10f05d..7ce9cbe09 100644
--- a/src/libcharon/plugins/ha/ha_message.c
+++ b/src/libcharon/plugins/ha/ha_message.c
@@ -46,6 +46,20 @@ struct private_ha_message_t {
chunk_t buf;
};
+ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
+ "IKE_ADD",
+ "IKE_UPDATE",
+ "IKE_MID_INITIATOR",
+ "IKE_MID_RESPONDER",
+ "IKE_DELETE",
+ "CHILD_ADD",
+ "CHILD_DELETE",
+ "SEGMENT_DROP",
+ "SEGMENT_TAKE",
+ "STATUS",
+ "RESYNC",
+);
+
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
/**
@@ -93,10 +107,8 @@ struct ts_encoding_t {
char encoding[];
} __attribute__((packed));
-/**
- * Implementation of ha_message_t.get_type
- */
-static ha_message_type_t get_type(private_ha_message_t *this)
+METHOD(ha_message_t, get_type, ha_message_type_t,
+ private_ha_message_t *this)
{
return this->buf.ptr[1];
}
@@ -119,11 +131,8 @@ static void check_buf(private_ha_message_t *this, size_t len)
}
}
-/**
- * Implementation of ha_message_t.add_attribute
- */
-static void add_attribute(private_ha_message_t *this,
- ha_message_attribute_t attribute, ...)
+METHOD(ha_message_t, add_attribute, void,
+ private_ha_message_t *this, ha_message_attribute_t attribute, ...)
{
size_t len;
va_list args;
@@ -154,6 +163,7 @@ static void add_attribute(private_ha_message_t *this,
/* identification_t* */
case HA_LOCAL_ID:
case HA_REMOTE_ID:
+ case HA_REMOTE_EAP_ID:
{
identification_encoding_t *enc;
identification_t *id;
@@ -203,6 +213,7 @@ static void add_attribute(private_ha_message_t *this,
break;
}
/* u_int8_t */
+ case HA_INITIATOR:
case HA_IPSEC_MODE:
case HA_IPCOMP:
{
@@ -237,8 +248,7 @@ static void add_attribute(private_ha_message_t *this,
case HA_EXTENSIONS:
case HA_INBOUND_SPI:
case HA_OUTBOUND_SPI:
- case HA_INITIATE_MID:
- case HA_RESPOND_MID:
+ case HA_MID:
{
u_int32_t val;
@@ -310,12 +320,9 @@ typedef struct {
void *cleanup_data;
} attribute_enumerator_t;
-/**
- * Implementation of create_attribute_enumerator().enumerate
- */
-static bool attribute_enumerate(attribute_enumerator_t *this,
- ha_message_attribute_t *attr_out,
- ha_message_value_t *value)
+METHOD(enumerator_t, attribute_enumerate, bool,
+ attribute_enumerator_t *this, ha_message_attribute_t *attr_out,
+ ha_message_value_t *value)
{
ha_message_attribute_t attr;
@@ -354,6 +361,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
/* identification_t* */
case HA_LOCAL_ID:
case HA_REMOTE_ID:
+ case HA_REMOTE_EAP_ID:
{
identification_encoding_t *enc;
@@ -417,6 +425,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
return TRUE;
}
/* u_int8_t */
+ case HA_INITIATOR:
case HA_IPSEC_MODE:
case HA_IPCOMP:
{
@@ -453,8 +462,7 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
case HA_EXTENSIONS:
case HA_INBOUND_SPI:
case HA_OUTBOUND_SPI:
- case HA_INITIATE_MID:
- case HA_RESPOND_MID:
+ case HA_MID:
{
if (this->buf.len < sizeof(u_int32_t))
{
@@ -559,10 +567,8 @@ static bool attribute_enumerate(attribute_enumerator_t *this,
}
}
-/**
- * Implementation of create_attribute_enumerator().destroy
- */
-static void enum_destroy(attribute_enumerator_t *this)
+METHOD(enumerator_t, enum_destroy, void,
+ attribute_enumerator_t *this)
{
if (this->cleanup)
{
@@ -571,35 +577,30 @@ static void enum_destroy(attribute_enumerator_t *this)
free(this);
}
-/**
- * Implementation of ha_message_t.create_attribute_enumerator
- */
-static enumerator_t* create_attribute_enumerator(private_ha_message_t *this)
+METHOD(ha_message_t, create_attribute_enumerator, enumerator_t*,
+ private_ha_message_t *this)
{
- attribute_enumerator_t *e = malloc_thing(attribute_enumerator_t);
-
- e->public.enumerate = (void*)attribute_enumerate;
- e->public.destroy = (void*)enum_destroy;
+ attribute_enumerator_t *e;
- e->buf = chunk_skip(this->buf, 2);
- e->cleanup = NULL;
- e->cleanup_data = NULL;
+ INIT(e,
+ .public = {
+ .enumerate = (void*)_attribute_enumerate,
+ .destroy = _enum_destroy,
+ },
+ .buf = chunk_skip(this->buf, 2),
+ );
return &e->public;
}
-/**
- * Implementation of ha_message_t.get_encoding
- */
-static chunk_t get_encoding(private_ha_message_t *this)
+METHOD(ha_message_t, get_encoding, chunk_t,
+ private_ha_message_t *this)
{
return this->buf;
}
-/**
- * Implementation of ha_message_t.destroy.
- */
-static void destroy(private_ha_message_t *this)
+METHOD(ha_message_t, destroy, void,
+ private_ha_message_t *this)
{
free(this->buf.ptr);
free(this);
@@ -608,14 +609,17 @@ static void destroy(private_ha_message_t *this)
static private_ha_message_t *ha_message_create_generic()
{
- private_ha_message_t *this = malloc_thing(private_ha_message_t);
-
- this->public.get_type = (ha_message_type_t(*)(ha_message_t*))get_type;
- this->public.add_attribute = (void(*)(ha_message_t*, ha_message_attribute_t attribute, ...))add_attribute;
- this->public.create_attribute_enumerator = (enumerator_t*(*)(ha_message_t*))create_attribute_enumerator;
- this->public.get_encoding = (chunk_t(*)(ha_message_t*))get_encoding;
- this->public.destroy = (void(*)(ha_message_t*))destroy;
+ private_ha_message_t *this;
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .add_attribute = _add_attribute,
+ .create_attribute_enumerator = _create_attribute_enumerator,
+ .get_encoding = _get_encoding,
+ .destroy = _destroy,
+ },
+ );
return this;
}
diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h
index b2bc23724..50e11830f 100644
--- a/src/libcharon/plugins/ha/ha_message.h
+++ b/src/libcharon/plugins/ha/ha_message.h
@@ -30,7 +30,7 @@
/**
* Protocol version of this implementation
*/
-#define HA_MESSAGE_VERSION 1
+#define HA_MESSAGE_VERSION 2
typedef struct ha_message_t ha_message_t;
typedef enum ha_message_type_t ha_message_type_t;
@@ -43,8 +43,12 @@ typedef union ha_message_value_t ha_message_value_t;
enum ha_message_type_t {
/** add a completely new IKE_SA */
HA_IKE_ADD = 1,
- /** update an existing IKE_SA (message IDs, address update, ...) */
+ /** update an existing IKE_SA (identities, address update, ...) */
HA_IKE_UPDATE,
+ /** update initiator message id */
+ HA_IKE_MID_INITIATOR,
+ /** update responder message id */
+ HA_IKE_MID_RESPONDER,
/** delete an existing IKE_SA */
HA_IKE_DELETE,
/** add a new CHILD_SA */
@@ -62,6 +66,11 @@ enum ha_message_type_t {
};
/**
+ * Enum names for message types
+ */
+extern enum_name_t *ha_message_type_names;
+
+/**
* Type of attributes contained in a message
*/
enum ha_message_attribute_t {
@@ -73,6 +82,8 @@ enum ha_message_attribute_t {
HA_LOCAL_ID,
/** identification_t*, remote identity */
HA_REMOTE_ID,
+ /** identification_t*, remote EAP identity */
+ HA_REMOTE_EAP_ID,
/** host_t*, local address */
HA_LOCAL_ADDR,
/** host_t*, remote address */
@@ -89,6 +100,8 @@ enum ha_message_attribute_t {
HA_REMOTE_VIP,
/** host_t*, additional MOBIKE peer address */
HA_ADDITIONAL_ADDR,
+ /** u_int8_t, initiator of an exchange, TRUE for local */
+ HA_INITIATOR,
/** chunk_t, initiators nonce */
HA_NONCE_I,
/** chunk_t, responders nonce */
@@ -123,10 +136,8 @@ enum ha_message_attribute_t {
HA_LOCAL_TS,
/** traffic_selector_t*, remote traffic selector */
HA_REMOTE_TS,
- /** u_int32_t, initiating message ID */
- HA_INITIATE_MID,
- /** u_int32_t, responding message ID */
- HA_RESPOND_MID,
+ /** u_int32_t, message ID */
+ HA_MID,
/** u_int16_t, HA segment */
HA_SEGMENT,
};
@@ -190,7 +201,6 @@ struct ha_message_t {
/**
* Create a new ha_message instance, ready for adding attributes
*
- * @param version protocol version to create a message from
* @param type type of the message
*/
ha_message_t *ha_message_create(ha_message_type_t type);
@@ -202,4 +212,4 @@ ha_message_t *ha_message_create(ha_message_type_t type);
*/
ha_message_t *ha_message_parse(chunk_t data);
-#endif /* HA_MESSAGE_ @}*/
+#endif /** HA_MESSAGE_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
index ea255c8ab..e722b4f3a 100644
--- a/src/libcharon/plugins/ha/ha_plugin.c
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -21,8 +21,11 @@
#include "ha_dispatcher.h"
#include "ha_segments.h"
#include "ha_ctl.h"
+#include "ha_cache.h"
+#include "ha_attribute.h"
#include <daemon.h>
+#include <hydra.h>
#include <config/child_cfg.h>
typedef struct private_ha_plugin_t private_ha_plugin_t;
@@ -76,20 +79,31 @@ struct private_ha_plugin_t {
* Segment control interface via FIFO
*/
ha_ctl_t *ctl;
+
+ /**
+ * Message cache for resynchronization
+ */
+ ha_cache_t *cache;
+
+ /**
+ * Attribute provider
+ */
+ ha_attribute_t *attr;
};
-/**
- * Implementation of plugin_t.destroy
- */
-static void destroy(private_ha_plugin_t *this)
+METHOD(plugin_t, destroy, void,
+ private_ha_plugin_t *this)
{
DESTROY_IF(this->ctl);
+ hydra->attributes->remove_provider(hydra->attributes, &this->attr->provider);
charon->bus->remove_listener(charon->bus, &this->segments->listener);
charon->bus->remove_listener(charon->bus, &this->ike->listener);
charon->bus->remove_listener(charon->bus, &this->child->listener);
this->ike->destroy(this->ike);
this->child->destroy(this->child);
this->dispatcher->destroy(this->dispatcher);
+ this->attr->destroy(this->attr);
+ this->cache->destroy(this->cache);
this->segments->destroy(this->segments);
this->kernel->destroy(this->kernel);
this->socket->destroy(this->socket);
@@ -127,11 +141,9 @@ plugin_t *ha_plugin_create()
return NULL;
}
- this = malloc_thing(private_ha_plugin_t);
-
- this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
- this->tunnel = NULL;
- this->ctl = NULL;
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ );
if (secret)
{
@@ -146,17 +158,22 @@ plugin_t *ha_plugin_create()
}
this->kernel = ha_kernel_create(count);
this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
- count, strcmp(local, remote) > 0, monitor, resync);
+ count, strcmp(local, remote) > 0, monitor);
+ this->cache = ha_cache_create(this->kernel, this->socket, resync, count);
if (fifo)
{
- this->ctl = ha_ctl_create(this->segments);
+ this->ctl = ha_ctl_create(this->segments, this->cache);
}
- this->dispatcher = ha_dispatcher_create(this->socket, this->segments);
- this->ike = ha_ike_create(this->socket, this->tunnel);
- this->child = ha_child_create(this->socket, this->tunnel);
+ this->attr = ha_attribute_create(this->kernel, this->segments);
+ this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
+ this->cache, this->kernel, this->attr);
+ this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
+ this->child = ha_child_create(this->socket, this->tunnel, this->segments,
+ this->kernel);
charon->bus->add_listener(charon->bus, &this->segments->listener);
charon->bus->add_listener(charon->bus, &this->ike->listener);
charon->bus->add_listener(charon->bus, &this->child->listener);
+ hydra->attributes->add_provider(hydra->attributes, &this->attr->provider);
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/ha/ha_plugin.h b/src/libcharon/plugins/ha/ha_plugin.h
index 1ae2fe6dd..d4d746f91 100644
--- a/src/libcharon/plugins/ha/ha_plugin.h
+++ b/src/libcharon/plugins/ha/ha_plugin.h
@@ -44,4 +44,4 @@ struct ha_plugin_t {
plugin_t plugin;
};
-#endif /* HA_PLUGIN_H_ @}*/
+#endif /** HA_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_segments.c b/src/libcharon/plugins/ha/ha_segments.c
index 2199671fc..be2d7e428 100644
--- a/src/libcharon/plugins/ha/ha_segments.c
+++ b/src/libcharon/plugins/ha/ha_segments.c
@@ -22,8 +22,8 @@
#include <utils/linked_list.h>
#include <processing/jobs/callback_job.h>
-#define HEARTBEAT_DELAY 1000
-#define HEARTBEAT_TIMEOUT 2100
+#define DEFAULT_HEARTBEAT_DELAY 1000
+#define DEFAULT_HEARTBEAT_TIMEOUT 2100
typedef struct private_ha_segments_t private_ha_segments_t;
@@ -81,6 +81,16 @@ struct private_ha_segments_t {
* Node number
*/
u_int node;
+
+ /**
+ * Interval we send hearbeats
+ */
+ int heartbeat_delay;
+
+ /**
+ * Timeout for heartbeats received from other node
+ */
+ int heartbeat_timeout;
};
/**
@@ -168,8 +178,8 @@ static void enable_disable(private_ha_segments_t *this, u_int segment,
{
continue;
}
- if (this->kernel->in_segment(this->kernel,
- ike_sa->get_other_host(ike_sa), segment))
+ if (this->kernel->get_segment(this->kernel,
+ ike_sa->get_other_host(ike_sa)) == segment)
{
ike_sa->set_state(ike_sa, new);
}
@@ -183,6 +193,7 @@ static void enable_disable(private_ha_segments_t *this, u_int segment,
message = ha_message_create(type);
message->add_attribute(message, HA_SEGMENT, segment);
this->socket->push(this->socket, message);
+ message->destroy(message);
}
}
@@ -209,135 +220,37 @@ static void enable_disable_all(private_ha_segments_t *this, u_int segment,
this->mutex->unlock(this->mutex);
}
-/**
- * Implementation of ha_segments_t.activate
- */
-static void activate(private_ha_segments_t *this, u_int segment, bool notify)
+METHOD(ha_segments_t, activate, void,
+ private_ha_segments_t *this, u_int segment, bool notify)
{
enable_disable_all(this, segment, TRUE, notify);
}
-/**
- * Implementation of ha_segments_t.deactivate
- */
-static void deactivate(private_ha_segments_t *this, u_int segment, bool notify)
+METHOD(ha_segments_t, deactivate, void,
+ private_ha_segments_t *this, u_int segment, bool notify)
{
enable_disable_all(this, segment, FALSE, notify);
}
-/**
- * Rekey all children of an IKE_SA
- */
-static status_t rekey_children(ike_sa_t *ike_sa)
+METHOD(listener_t, alert_hook, bool,
+ private_ha_segments_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args)
{
- iterator_t *iterator;
- child_sa_t *child_sa;
- status_t status = SUCCESS;
-
- iterator = ike_sa->create_child_sa_iterator(ike_sa);
- while (iterator->iterate(iterator, (void**)&child_sa))
- {
- DBG1(DBG_CFG, "resyncing CHILD_SA");
- status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
- child_sa->get_spi(child_sa, TRUE));
- if (status == DESTROY_ME)
- {
- break;
- }
- }
- iterator->destroy(iterator);
- return status;
-}
-
-/**
- * Implementation of ha_segments_t.resync
- */
-static void resync(private_ha_segments_t *this, u_int segment)
-{
- ike_sa_t *ike_sa;
- enumerator_t *enumerator;
- linked_list_t *list;
- ike_sa_id_t *id;
-
- list = linked_list_create();
- this->mutex->lock(this->mutex);
-
- if (segment > 0 && segment <= this->count)
+ if (alert == ALERT_SHUTDOWN_SIGNAL)
{
- DBG1(DBG_CFG, "resyncing HA segment %d", segment);
-
- /* we do the actual rekeying in a seperate loop to avoid rekeying
- * an SA twice. */
- enumerator = charon->ike_sa_manager->create_enumerator(
- charon->ike_sa_manager);
- while (enumerator->enumerate(enumerator, &ike_sa))
+ if (this->job)
{
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
- this->kernel->in_segment(this->kernel,
- ike_sa->get_other_host(ike_sa), segment))
- {
- id = ike_sa->get_id(ike_sa);
- list->insert_last(list, id->clone(id));
- }
+ DBG1(DBG_CFG, "HA heartbeat active, dropping all segments");
+ deactivate(this, 0, TRUE);
}
- enumerator->destroy(enumerator);
- }
- this->mutex->unlock(this->mutex);
-
- while (list->remove_last(list, (void**)&id) == SUCCESS)
- {
- ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
- id->destroy(id);
- if (ike_sa)
+ else
{
- DBG1(DBG_CFG, "resyncing IKE_SA");
- if (ike_sa->rekey(ike_sa) != DESTROY_ME)
- {
- if (rekey_children(ike_sa) != DESTROY_ME)
- {
- charon->ike_sa_manager->checkin(
- charon->ike_sa_manager, ike_sa);
- continue;
- }
- }
- charon->ike_sa_manager->checkin_and_destroy(
- charon->ike_sa_manager, ike_sa);
+ DBG1(DBG_CFG, "no HA heartbeat active, closing IKE_SAs");
}
}
- list->destroy(list);
-}
-
-/**
- * Implementation of listener_t.alert
- */
-static bool alert_hook(private_ha_segments_t *this, ike_sa_t *ike_sa,
- alert_t alert, va_list args)
-{
- if (alert == ALERT_SHUTDOWN_SIGNAL)
- {
- deactivate(this, 0, TRUE);
- }
return TRUE;
}
/**
- * Request a resync of all segments
- */
-static job_requeue_t request_resync(private_ha_segments_t *this)
-{
- ha_message_t *message;
- int i;
-
- message = ha_message_create(HA_RESYNC);
- for (i = 1; i <= this->count; i++)
- {
- message->add_attribute(message, HA_SEGMENT, i);
- }
- this->socket->push(this->socket, message);
- return JOB_REQUEUE_NONE;
-}
-
-/**
* Monitor heartbeat activity of remote node
*/
static job_requeue_t watchdog(private_ha_segments_t *this)
@@ -349,7 +262,7 @@ static job_requeue_t watchdog(private_ha_segments_t *this)
pthread_cleanup_push((void*)this->mutex->unlock, this->mutex);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
timeout = this->condvar->timed_wait(this->condvar, this->mutex,
- HEARTBEAT_TIMEOUT);
+ this->heartbeat_timeout);
pthread_setcancelstate(oldstate, NULL);
pthread_cleanup_pop(TRUE);
if (timeout)
@@ -373,10 +286,8 @@ static void start_watchdog(private_ha_segments_t *this)
charon->processor->queue_job(charon->processor, (job_t*)this->job);
}
-/**
- * Implementation of ha_segments_t.handle_status
- */
-static void handle_status(private_ha_segments_t *this, segment_mask_t mask)
+METHOD(ha_segments_t, handle_status, void,
+ private_ha_segments_t *this, segment_mask_t mask)
{
segment_mask_t missing;
int i;
@@ -431,20 +342,25 @@ static job_requeue_t send_status(private_ha_segments_t *this)
}
this->socket->push(this->socket, message);
+ message->destroy(message);
/* schedule next invocation */
charon->scheduler->schedule_job_ms(charon->scheduler, (job_t*)
callback_job_create((callback_job_cb_t)
send_status, this, NULL, NULL),
- HEARTBEAT_DELAY);
+ this->heartbeat_delay);
return JOB_REQUEUE_NONE;
}
-/**
- * Implementation of ha_segments_t.destroy.
- */
-static void destroy(private_ha_segments_t *this)
+METHOD(ha_segments_t, is_active, bool,
+ private_ha_segments_t *this, u_int segment)
+{
+ return (this->active & SEGMENTS_BIT(segment)) != 0;
+}
+
+METHOD(ha_segments_t, destroy, void,
+ private_ha_segments_t *this)
{
if (this->job)
{
@@ -460,44 +376,40 @@ static void destroy(private_ha_segments_t *this)
*/
ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
ha_tunnel_t *tunnel, u_int count, u_int node,
- bool monitor, bool sync)
+ bool monitor)
{
- private_ha_segments_t *this = malloc_thing(private_ha_segments_t);
-
- memset(&this->public.listener, 0, sizeof(listener_t));
- this->public.listener.alert = (bool(*)(listener_t*, ike_sa_t *, alert_t, va_list))alert_hook;
- this->public.activate = (void(*)(ha_segments_t*, u_int segment,bool))activate;
- this->public.deactivate = (void(*)(ha_segments_t*, u_int segment,bool))deactivate;
- this->public.resync = (void(*)(ha_segments_t*, u_int segment))resync;
- this->public.handle_status = (void(*)(ha_segments_t*, segment_mask_t mask))handle_status;
- this->public.destroy = (void(*)(ha_segments_t*))destroy;
-
- this->socket = socket;
- this->tunnel = tunnel;
- this->kernel = kernel;
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
- this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
- this->count = count;
- this->node = node;
- this->job = NULL;
-
- /* initially all segments are deactivated */
- this->active = 0;
+ private_ha_segments_t *this;
+
+ INIT(this,
+ .public = {
+ .listener.alert = _alert_hook,
+ .activate = _activate,
+ .deactivate = _deactivate,
+ .handle_status = _handle_status,
+ .is_active = _is_active,
+ .destroy = _destroy,
+ },
+ .socket = socket,
+ .tunnel = tunnel,
+ .kernel = kernel,
+ .count = count,
+ .node = node,
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
+ .heartbeat_delay = lib->settings->get_int(lib->settings,
+ "charon.plugins.ha.heartbeat_delay", DEFAULT_HEARTBEAT_DELAY),
+ .heartbeat_timeout = lib->settings->get_int(lib->settings,
+ "charon.plugins.ha.heartbeat_timeout", DEFAULT_HEARTBEAT_TIMEOUT),
+ );
if (monitor)
{
+ DBG1(DBG_CFG, "starting HA heartbeat, delay %dms, timeout %dms",
+ this->heartbeat_delay, this->heartbeat_timeout);
send_status(this);
start_watchdog(this);
}
- if (sync)
- {
- /* request a resync as soon as we are up */
- charon->processor->queue_job(charon->processor, (job_t*)
- callback_job_create((callback_job_cb_t)request_resync,
- this, NULL, NULL));
- }
-
return &this->public;
}
diff --git a/src/libcharon/plugins/ha/ha_segments.h b/src/libcharon/plugins/ha/ha_segments.h
index 6d1cd5441..eb9e5c1d5 100644
--- a/src/libcharon/plugins/ha/ha_segments.h
+++ b/src/libcharon/plugins/ha/ha_segments.h
@@ -68,23 +68,19 @@ struct ha_segments_t {
void (*deactivate)(ha_segments_t *this, u_int segment, bool notify);
/**
- * Resync an active segment.
- *
- * To reintegrade a node into the cluster, resynchronization is reqired.
- * IKE_SAs and CHILD_SAs are synced automatically during rekeying. A call
- * to this method enforces a rekeying immediately sync all state of a
- * segment.
+ * Handle a status message from the remote node.
*
- * @param segment segment to resync
+ * @param mask segments the remote node is serving actively
*/
- void (*resync)(ha_segments_t *this, u_int segment);
+ void (*handle_status)(ha_segments_t *this, segment_mask_t mask);
/**
- * Handle a status message from the remote node.
+ * Check if a given segment is currently active.
*
- * @param mask segments the remote node is serving actively
+ * @param segment segment to check
+ * @return TRUE if segment active
*/
- void (*handle_status)(ha_segments_t *this, segment_mask_t mask);
+ bool (*is_active)(ha_segments_t *this, u_int segment);
/**
* Destroy a ha_segments_t.
@@ -101,11 +97,10 @@ struct ha_segments_t {
* @param count number of segments the cluster uses
* @param node node, currently 1 or 0
* @param monitor should we use monitoring functionality
- * @param resync request a complete resync on startup
* @return segment object
*/
ha_segments_t *ha_segments_create(ha_socket_t *socket, ha_kernel_t *kernel,
ha_tunnel_t *tunnel, u_int count, u_int node,
- bool monitor, bool resync);
+ bool monitor);
-#endif /* HA_SEGMENTS_ @}*/
+#endif /** HA_SEGMENTS_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_socket.c b/src/libcharon/plugins/ha/ha_socket.c
index b84b02868..21e6eb6d5 100644
--- a/src/libcharon/plugins/ha/ha_socket.c
+++ b/src/libcharon/plugins/ha/ha_socket.c
@@ -58,8 +58,8 @@ struct private_ha_socket_t {
* Data to pass to the send_message() callback job
*/
typedef struct {
- ha_message_t *message;
- private_ha_socket_t *this;
+ chunk_t chunk;
+ int fd;
} job_data_t;
/**
@@ -67,7 +67,7 @@ typedef struct {
*/
static void job_data_destroy(job_data_t *this)
{
- this->message->destroy(this->message);
+ free(this->chunk.ptr);
free(this);
}
@@ -76,22 +76,15 @@ static void job_data_destroy(job_data_t *this)
*/
static job_requeue_t send_message(job_data_t *data)
{
- private_ha_socket_t *this;
- chunk_t chunk;
-
- this = data->this;
- chunk = data->message->get_encoding(data->message);
- if (send(this->fd, chunk.ptr, chunk.len, 0) < chunk.len)
+ if (send(data->fd, data->chunk.ptr, data->chunk.len, 0) < data->chunk.len)
{
DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
}
return JOB_REQUEUE_NONE;
}
-/**
- * Implementation of ha_socket_t.push
- */
-static void push(private_ha_socket_t *this, ha_message_t *message)
+METHOD(ha_socket_t, push, void,
+ private_ha_socket_t *this, ha_message_t *message)
{
chunk_t chunk;
@@ -107,9 +100,10 @@ static void push(private_ha_socket_t *this, ha_message_t *message)
/* Fallback to asynchronous transmission. This is required, as sendto()
* is a blocking call if it acquires a policy. We could end up in a
* deadlock, as we own an IKE_SA. */
- data = malloc_thing(job_data_t);
- data->message = message;
- data->this = this;
+ INIT(data,
+ .chunk = chunk_clone(chunk),
+ .fd = this->fd,
+ );
job = callback_job_create((callback_job_cb_t)send_message,
data, (void*)job_data_destroy, NULL);
@@ -118,13 +112,10 @@ static void push(private_ha_socket_t *this, ha_message_t *message)
}
DBG1(DBG_CFG, "pushing HA message failed: %s", strerror(errno));
}
- message->destroy(message);
}
-/**
- * Implementation of ha_socket_t.pull
- */
-static ha_message_t *pull(private_ha_socket_t *this)
+METHOD(ha_socket_t, pull, ha_message_t*,
+ private_ha_socket_t *this)
{
while (TRUE)
{
@@ -189,10 +180,8 @@ static bool open_socket(private_ha_socket_t *this)
return TRUE;
}
-/**
- * Implementation of ha_socket_t.destroy.
- */
-static void destroy(private_ha_socket_t *this)
+METHOD(ha_socket_t, destroy, void,
+ private_ha_socket_t *this)
{
if (this->fd != -1)
{
@@ -208,15 +197,18 @@ static void destroy(private_ha_socket_t *this)
*/
ha_socket_t *ha_socket_create(char *local, char *remote)
{
- private_ha_socket_t *this = malloc_thing(private_ha_socket_t);
-
- this->public.push = (void(*)(ha_socket_t*, ha_message_t*))push;
- this->public.pull = (ha_message_t*(*)(ha_socket_t*))pull;
- this->public.destroy = (void(*)(ha_socket_t*))destroy;
+ private_ha_socket_t *this;
- this->local = host_create_from_dns(local, 0, HA_PORT);
- this->remote = host_create_from_dns(remote, 0, HA_PORT);
- this->fd = -1;
+ INIT(this,
+ .public = {
+ .push = _push,
+ .pull = _pull,
+ .destroy = _destroy,
+ },
+ .local = host_create_from_dns(local, 0, HA_PORT),
+ .remote = host_create_from_dns(remote, 0, HA_PORT),
+ .fd = -1,
+ );
if (!this->local || !this->remote)
{
diff --git a/src/libcharon/plugins/ha/ha_socket.h b/src/libcharon/plugins/ha/ha_socket.h
index 8d398e22b..a4789a51d 100644
--- a/src/libcharon/plugins/ha/ha_socket.h
+++ b/src/libcharon/plugins/ha/ha_socket.h
@@ -35,7 +35,7 @@ struct ha_socket_t {
/**
* Push synchronization information to the responsible node.
*
- * @param message message to send, gets destroyed by push()
+ * @param message message to send
*/
void (*push)(ha_socket_t *this, ha_message_t *message);
@@ -57,4 +57,4 @@ struct ha_socket_t {
*/
ha_socket_t *ha_socket_create(char *local, char *remote);
-#endif /* HA_SOCKET_ @}*/
+#endif /** HA_SOCKET_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index b3511e5f0..fef84a430 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -92,10 +92,8 @@ struct private_ha_tunnel_t {
ha_creds_t creds;
};
-/**
- * Implementation of ha_tunnel_t.is_sa
- */
-static bool is_sa(private_ha_tunnel_t *this, ike_sa_t *ike_sa)
+METHOD(ha_tunnel_t, is_sa, bool,
+ private_ha_tunnel_t *this, ike_sa_t *ike_sa)
{
peer_cfg_t *cfg = this->backend.cfg;
@@ -112,11 +110,8 @@ typedef struct {
shared_key_t *key;
} shared_enum_t;
-/**
- * Implementation of shared_enum_t.enumerate
- */
-static bool shared_enumerate(shared_enum_t *this, shared_key_t **key,
- id_match_t *me, id_match_t *other)
+METHOD(enumerator_t, shared_enumerate, bool,
+ shared_enum_t *this, shared_key_t **key, id_match_t *me, id_match_t *other)
{
if (this->key)
{
@@ -135,12 +130,9 @@ static bool shared_enumerate(shared_enum_t *this, shared_key_t **key,
return FALSE;
}
-/**
- * Implements ha_creds_t.create_shared_enumerator
- */
-static enumerator_t* create_shared_enumerator(ha_creds_t *this,
- shared_key_type_t type, identification_t *me,
- identification_t *other)
+METHOD(ha_creds_t, create_shared_enumerator, enumerator_t*,
+ ha_creds_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
{
shared_enum_t *enumerator;
@@ -157,28 +149,25 @@ static enumerator_t* create_shared_enumerator(ha_creds_t *this,
return NULL;
}
- enumerator = malloc_thing(shared_enum_t);
- enumerator->public.enumerate = (void*)shared_enumerate;
- enumerator->public.destroy = (void*)free;
- enumerator->key = this->key;
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_shared_enumerate,
+ .destroy = (void*)free,
+ },
+ .key = this->key,
+ );
return &enumerator->public;
}
-/**
- * Implementation of backend_t.create_peer_cfg_enumerator.
- */
-static enumerator_t* create_peer_cfg_enumerator(ha_backend_t *this,
- identification_t *me, identification_t *other)
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+ ha_backend_t *this, identification_t *me, identification_t *other)
{
return enumerator_create_single(this->cfg, NULL);
}
-/**
- * Implementation of backend_t.create_ike_cfg_enumerator.
- */
-static enumerator_t* create_ike_cfg_enumerator(ha_backend_t *this,
- host_t *me, host_t *other)
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+ ha_backend_t *this, host_t *me, host_t *other)
{
return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL);
}
@@ -207,11 +196,11 @@ static void setup_tunnel(private_ha_tunnel_t *this,
chunk_clone(chunk_create(secret, strlen(secret))));
this->creds.public.create_private_enumerator = (void*)return_null;
this->creds.public.create_cert_enumerator = (void*)return_null;
- this->creds.public.create_shared_enumerator = (void*)create_shared_enumerator;
+ this->creds.public.create_shared_enumerator = (void*)_create_shared_enumerator;
this->creds.public.create_cdp_enumerator = (void*)return_null;
this->creds.public.cache_cert = (void*)nop;
- charon->credentials->add_set(charon->credentials, &this->creds.public);
+ lib->credmgr->add_set(lib->credmgr, &this->creds.public);
/* create config and backend */
ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT,
@@ -233,8 +222,9 @@ static void setup_tunnel(private_ha_tunnel_t *this,
identification_create_from_string(remote));
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
- child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE,
- MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
@@ -247,8 +237,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
peer_cfg->add_child_cfg(peer_cfg, child_cfg);
this->backend.cfg = peer_cfg;
- this->backend.public.create_peer_cfg_enumerator = (void*)create_peer_cfg_enumerator;
- this->backend.public.create_ike_cfg_enumerator = (void*)create_ike_cfg_enumerator;
+ this->backend.public.create_peer_cfg_enumerator = (void*)_create_peer_cfg_enumerator;
+ this->backend.public.create_ike_cfg_enumerator = (void*)_create_ike_cfg_enumerator;
this->backend.public.get_peer_cfg_by_name = (void*)return_null;
charon->backends->add_backend(charon->backends, &this->backend.public);
@@ -257,10 +247,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg);
}
-/**
- * Implementation of ha_tunnel_t.destroy.
- */
-static void destroy(private_ha_tunnel_t *this)
+METHOD(ha_tunnel_t, destroy, void,
+ private_ha_tunnel_t *this)
{
if (this->backend.cfg)
{
@@ -269,7 +257,7 @@ static void destroy(private_ha_tunnel_t *this)
}
if (this->creds.key)
{
- charon->credentials->remove_set(charon->credentials, &this->creds.public);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds.public);
this->creds.key->destroy(this->creds.key);
}
this->creds.local->destroy(this->creds.local);
@@ -286,10 +274,14 @@ static void destroy(private_ha_tunnel_t *this)
*/
ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret)
{
- private_ha_tunnel_t *this = malloc_thing(private_ha_tunnel_t);
+ private_ha_tunnel_t *this;
- this->public.is_sa = (bool(*)(ha_tunnel_t*, ike_sa_t *ike_sa))is_sa;
- this->public.destroy = (void(*)(ha_tunnel_t*))destroy;
+ INIT(this,
+ .public = {
+ .is_sa = _is_sa,
+ .destroy = _destroy,
+ },
+ );
setup_tunnel(this, local, remote, secret);
diff --git a/src/libcharon/plugins/ha/ha_tunnel.h b/src/libcharon/plugins/ha/ha_tunnel.h
index 085fb6122..549e33055 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.h
+++ b/src/libcharon/plugins/ha/ha_tunnel.h
@@ -54,4 +54,4 @@ struct ha_tunnel_t {
*/
ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret);
-#endif /* HA_TUNNEL_H_ @}*/
+#endif /** HA_TUNNEL_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_klips/Makefile.in b/src/libcharon/plugins/kernel_klips/Makefile.in
index f0d112a0f..9cac89ec3 100644
--- a/src/libcharon/plugins/kernel_klips/Makefile.in
+++ b/src/libcharon/plugins/kernel_klips/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
index 01df4f71a..6b5aeb342 100644
--- a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -1690,10 +1690,11 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
- u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
- bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1849,7 +1850,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_klips_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1920,14 +1921,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
return NOT_SUPPORTED; /* TODO */
}
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1992,8 +1993,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -2210,7 +2211,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
#define IDLE_PREFIX "idle="
static const char *path_eroute = "/proc/net/ipsec_eroute";
@@ -2365,7 +2367,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg = (struct sadb_msg*)request, *out;
@@ -2574,7 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void,
{
close(this->socket);
}
- if (this->socket_evnets > 0)
+ if (this->socket_events > 0)
{
close(this->socket_events);
}
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in
index 8c9965467..49cc895bc 100644
--- a/src/libcharon/plugins/kernel_netlink/Makefile.in
+++ b/src/libcharon/plugins/kernel_netlink/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 1b8c1b879..019ec93f8 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -280,6 +280,9 @@ struct policy_entry_t {
/** parameters of installed policy */
struct xfrm_selector sel;
+ /** optional mark */
+ u_int32_t mark;
+
/** associated route installed for this policy */
route_entry_t *route;
@@ -292,7 +295,8 @@ struct policy_entry_t {
*/
static u_int policy_hash(policy_entry_t *key)
{
- chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+ chunk_t chunk = chunk_create((void*)&key->sel,
+ sizeof(struct xfrm_selector) + sizeof(u_int32_t));
return chunk_hash(chunk);
}
@@ -301,7 +305,8 @@ static u_int policy_hash(policy_entry_t *key)
*/
static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
{
- return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ return memeq(&key->sel, &other_key->sel,
+ sizeof(struct xfrm_selector) + sizeof(u_int32_t)) &&
key->direction == other_key->direction;
}
@@ -917,11 +922,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
- u_int16_t cpi, bool encap, bool inbound, traffic_selector_t* src_ts,
- traffic_selector_t* dst_ts)
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{
netlink_buf_t request;
char *alg_name;
@@ -934,8 +939,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (ipcomp != IPCOMP_NONE && cpi != 0)
{
lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
- add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, &lft,
- ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+ add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
+ &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
mode, ipcomp, 0, FALSE, inbound, NULL, NULL);
ipcomp = IPCOMP_NONE;
/* use transport mode ESP SA, IPComp uses tunnel mode */
@@ -944,9 +949,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
- ntohl(spi), reqid);
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} "
+ "(mark %u/0x%8x)", ntohl(spi), reqid, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
+ ntohl(spi), reqid);
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -1151,6 +1163,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (encap)
{
+ struct xfrm_encap_tmpl *tmpl;
+
rthdr->rta_type = XFRMA_ENCAP;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
@@ -1160,7 +1174,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
return FAILED;
}
- struct xfrm_encap_tmpl* tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
+ tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
tmpl->encap_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = htons(src->get_port(src));
tmpl->encap_dport = htons(dst->get_port(dst));
@@ -1177,9 +1191,36 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr = XFRM_RTA_NEXT(rthdr);
}
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x "
+ "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ }
return FAILED;
}
return SUCCESS;
@@ -1275,7 +1316,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1285,8 +1326,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
@@ -1298,6 +1346,24 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
sa_id->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst);
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ }
+
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
{
hdr = out;
@@ -1313,8 +1379,20 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
case NLMSG_ERROR:
{
struct nlmsgerr *err = NLMSG_DATA(hdr);
- DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)",
- ntohl(spi), strerror(-err->error), -err->error);
+
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+ "(mark %u/0x%8x) failed: %s (%d)",
+ ntohl(spi), mark.value, mark.mask,
+ strerror(-err->error), -err->error);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+ "failed: %s (%d)", ntohl(spi),
+ strerror(-err->error), -err->error);
+ }
break;
}
default:
@@ -1341,7 +1419,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
netlink_buf_t request;
struct nlmsghdr *hdr;
@@ -1350,13 +1428,20 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
/* if IPComp was used, we first delete the additional IPComp SA */
if (cpi)
{
- del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0);
+ del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
}
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELSA;
@@ -1368,19 +1453,53 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
sa_id->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst);
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ }
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
+ "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ }
return FAILED;
}
- DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ }
return SUCCESS;
}
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool old_encap, bool new_encap)
+ bool old_encap, bool new_encap, mark_t mark)
{
netlink_buf_t request;
u_char *pos;
@@ -1398,7 +1517,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
if (cpi)
{
update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
- src, dst, new_src, new_dst, FALSE, FALSE);
+ src, dst, new_src, new_dst, FALSE, FALSE, mark);
}
memset(&request, 0, sizeof(request));
@@ -1459,7 +1578,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
}
/* delete the old SA (without affecting the IPComp SA) */
- if (del_sa(this, src, dst, spi, protocol, 0) != SUCCESS)
+ if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
{
DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
free(out);
@@ -1558,8 +1677,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
policy_entry_t *current, *policy;
bool found = FALSE;
@@ -1571,6 +1690,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy = malloc_thing(policy_entry_t);
memset(policy, 0, sizeof(policy_entry_t));
policy->sel = ts2selector(src_ts, dst_ts);
+ policy->mark = mark.value & mark.mask;
policy->direction = direction;
/* find the policy, which matches EXACTLY */
@@ -1580,9 +1700,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
{
/* use existing policy */
current->refcount++;
- DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
- "refcount", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%8x) "
+ "already exists, increasing refcount",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "policy %R === %R %N "
+ "already exists, increasing refcount",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
free(policy);
policy = current;
found = TRUE;
@@ -1593,8 +1723,17 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy->refcount = 1;
}
- DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "adding policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "adding policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
memset(&request, 0, sizeof(request));
hdr = (struct nlmsghdr*)request;
@@ -1673,6 +1812,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = mode2kernel(mode);
tmpl->family = src->get_family(src);
+ rthdr = XFRM_RTA_NEXT(rthdr);
+
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ }
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
@@ -1741,7 +1899,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1751,9 +1910,17 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
@@ -1763,6 +1930,25 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
policy_id->sel = ts2selector(src_ts, dst_ts);
policy_id->dir = direction;
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ }
+
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
{
hdr = out;
@@ -1816,7 +2002,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
policy_entry_t *current, policy, *to_delete = NULL;
route_entry_t *route;
@@ -1824,12 +2011,22 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
- DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleting policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
/* create a policy */
memset(&policy, 0, sizeof(policy_entry_t));
policy.sel = ts2selector(src_ts, dst_ts);
+ policy.mark = mark.value & mark.mask;
policy.direction = direction;
/* find the policy */
@@ -1851,8 +2048,17 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
this->mutex->unlock(this->mutex);
if (!to_delete)
{
- DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
- dst_ts, policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) "
+ "failed, not found", src_ts, dst_ts, policy_dir_names,
+ direction, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
return NOT_FOUND;
}
@@ -1867,13 +2073,40 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_id->sel = to_delete->sel;
policy_id->dir = direction;
+ if (mark.value)
+ {
+ struct xfrm_mark *mrk;
+ struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
+
+ rthdr->rta_type = XFRMA_MARK;
+ rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
+ hdr->nlmsg_len += rthdr->rta_len;
+ if (hdr->nlmsg_len > sizeof(request))
+ {
+ return FAILED;
+ }
+
+ mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
+ mrk->v = mark.value;
+ mrk->m = mark.mask;
+ }
+
route = to_delete->route;
free(to_delete);
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N "
+ "(mark %u/0x%8x)", src_ts, dst_ts, policy_dir_names,
+ direction, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
return FAILED;
}
diff --git a/src/libcharon/plugins/kernel_pfkey/Makefile.in b/src/libcharon/plugins/kernel_pfkey/Makefile.in
index 2b028ba71..1dda6827b 100644
--- a/src/libcharon/plugins/kernel_pfkey/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfkey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 8a7883c8a..a64c27f6f 100644
--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
@@ -67,8 +67,10 @@
/** non linux specific */
#ifndef IPPROTO_COMP
+#ifdef IPPROTO_IPCOMP
#define IPPROTO_COMP IPPROTO_IPCOMP
#endif
+#endif
#ifndef SADB_X_AALG_SHA2_256HMAC
#define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256
@@ -600,17 +602,43 @@ static int lookup_algorithm(kernel_algorithm_t *list, int ikev2)
}
/**
- * add a host behind a sadb_address extension
+ * Copy a host_t as sockaddr_t to the given memory location. Ports are
+ * reset to zero as per RFC 2367.
+ * @return the number of bytes copied
*/
-static void host2ext(host_t *host, struct sadb_address *ext)
+static size_t hostcpy(void *dest, host_t *host)
{
- sockaddr_t *host_addr = host->get_sockaddr(host);
+ sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest;
socklen_t *len = host->get_sockaddr_len(host);
+ memcpy(dest, addr, *len);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- host_addr->sa_len = *len;
+ dest_addr->sa_len = *len;
#endif
- memcpy((char*)(ext + 1), host_addr, *len);
- ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len);
+ switch (dest_addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = dest;
+ sin->sin_port = 0;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = dest;
+ sin6->sin6_port = 0;
+ break;
+ }
+ }
+ return *len;
+}
+
+/**
+ * add a host behind an sadb_address extension
+ */
+static void host2ext(host_t *host, struct sadb_address *ext)
+{
+ size_t len = hostcpy(ext + 1, host);
+ ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + len);
}
/**
@@ -1019,7 +1047,7 @@ static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg*
}
#endif /*SADB_X_MIGRATE*/
-#ifdef HAVE_NATT
+#ifdef SADB_X_NAT_T_NEW_MAPPING
/**
* Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
*/
@@ -1075,7 +1103,7 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg*
}
}
}
-#endif /*HAVE_NATT*/
+#endif /*SADB_X_NAT_T_NEW_MAPPING*/
/**
* Receives events from kernel
@@ -1137,11 +1165,11 @@ static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this)
process_migrate(this, msg);
break;
#endif /*SADB_X_MIGRATE*/
-#ifdef HAVE_NATT
+#ifdef SADB_X_NAT_T_NEW_MAPPING
case SADB_X_NAT_T_NEW_MAPPING:
process_mapping(this, msg);
break;
-#endif /*HAVE_NATT*/
+#endif /*SADB_X_NAT_T_NEW_MAPPING*/
default:
break;
}
@@ -1217,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
- u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
- bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1364,7 +1393,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1497,7 +1526,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1553,7 +1582,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1604,8 +1633,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1679,14 +1708,10 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
if (mode == MODE_TUNNEL)
{
- sockaddr_t *sa;
- socklen_t sl;
- sa = src->get_sockaddr(src);
- sl = *src->get_sockaddr_len(src);
- memcpy(req + 1, sa, sl);
- sa = dst->get_sockaddr(dst);
- memcpy((u_int8_t*)(req + 1) + sl, sa, sl);
- req->sadb_x_ipsecrequest_len += sl * 2;
+ len = hostcpy(req + 1, src);
+ req->sadb_x_ipsecrequest_len += len;
+ len = hostcpy((char*)(req + 1) + len, dst);
+ req->sadb_x_ipsecrequest_len += len;
}
pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len);
@@ -1771,22 +1796,30 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net));
route->prefixlen = policy->src.mask;
- switch (charon->kernel_interface->add_route(charon->kernel_interface,
- route->dst_net, route->prefixlen, route->gateway,
- route->src_ip, route->if_name))
+ if (route->if_name)
+ {
+ switch (charon->kernel_interface->add_route(
+ charon->kernel_interface, route->dst_net,
+ route->prefixlen, route->gateway,
+ route->src_ip, route->if_name))
+ {
+ default:
+ DBG1(DBG_KNL, "unable to install source route for %H",
+ route->src_ip);
+ /* FALL */
+ case ALREADY_DONE:
+ /* route exists, do not uninstall */
+ route_entry_destroy(route);
+ break;
+ case SUCCESS:
+ /* cache the installed route */
+ policy->route = route;
+ break;
+ }
+ }
+ else
{
- default:
- DBG1(DBG_KNL, "unable to install source route for %H",
- route->src_ip);
- /* FALL */
- case ALREADY_DONE:
- /* route exists, do not uninstall */
- route_entry_destroy(route);
- break;
- case SUCCESS:
- /* cache the installed route */
- policy->route = route;
- break;
+ route_entry_destroy(route);
}
}
else
@@ -1802,7 +1835,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1905,7 +1939,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
diff --git a/src/libcharon/plugins/kernel_pfroute/Makefile.in b/src/libcharon/plugins/kernel_pfroute/Makefile.in
index 3a4d2c3b5..f78a97013 100644
--- a/src/libcharon/plugins/kernel_pfroute/Makefile.in
+++ b/src/libcharon/plugins/kernel_pfroute/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index 8965aff78..d049bb41b 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index c1f98f2fe..a230aa3f5 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -223,8 +223,9 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
generate_auth_cfg(this, this->initiator_auth, peer_cfg, FALSE, num);
}
- child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE,
- MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal);
ts = traffic_selector_create_dynamic(0, 0, 65535);
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 1218443cc..43c0ef009 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -34,118 +34,89 @@ struct private_load_tester_ipsec_t {
u_int32_t spi;
};
-/**
- * Implementation of kernel_interface_t.get_spi.
- */
-static status_t get_spi(private_load_tester_ipsec_t *this,
- host_t *src, host_t *dst,
- protocol_id_t protocol, u_int32_t reqid,
- u_int32_t *spi)
+METHOD(kernel_ipsec_t, get_spi, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi)
{
*spi = ++this->spi;
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.get_cpi.
- */
-static status_t get_cpi(private_load_tester_ipsec_t *this,
- host_t *src, host_t *dst,
- u_int32_t reqid, u_int16_t *cpi)
+METHOD(kernel_ipsec_t, get_cpi, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t reqid, u_int16_t *cpi)
{
return FAILED;
}
-/**
- * Implementation of kernel_interface_t.add_sa.
- */
-static status_t add_sa(private_load_tester_ipsec_t *this,
- host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid,
- lifetime_cfg_t *lifetime,
- u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool encap, bool inbound, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts)
+METHOD(kernel_ipsec_t, add_sa, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
{
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.update_sa.
- */
-static status_t update_sa(private_load_tester_ipsec_t *this,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
- host_t *src, host_t *dst,
- host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+METHOD(kernel_ipsec_t, update_sa, status_t,
+ private_load_tester_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
+ u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src,
+ host_t *new_dst, bool encap, bool new_encap, mark_t mark)
{
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.query_sa.
- */
-static status_t query_sa(private_load_tester_ipsec_t *this, host_t *src,
- host_t *dst, u_int32_t spi, protocol_id_t protocol,
- u_int64_t *bytes)
+METHOD(kernel_ipsec_t, query_sa, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
return NOT_SUPPORTED;
}
-/**
- * Implementation of kernel_interface_t.del_sa.
- */
-static status_t del_sa(private_load_tester_ipsec_t *this, host_t *src,
- host_t *dst, u_int32_t spi, protocol_id_t protocol,
- u_int16_t cpi)
+METHOD(kernel_ipsec_t, del_sa, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.add_policy.
- */
-static status_t add_policy(private_load_tester_ipsec_t *this,
- host_t *src, host_t *dst,
- traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+METHOD(kernel_ipsec_t, add_policy, status_t,
+ private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+ policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.query_policy.
- */
-static status_t query_policy(private_load_tester_ipsec_t *this,
- traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t *use_time)
+METHOD(kernel_ipsec_t, query_policy, status_t,
+ private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
*use_time = time_monotonic(NULL);
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.del_policy.
- */
-static status_t del_policy(private_load_tester_ipsec_t *this,
- traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts,
- policy_dir_t direction, bool unrouted)
+METHOD(kernel_ipsec_t, del_policy, status_t,
+ private_load_tester_ipsec_t *this, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
return SUCCESS;
}
-/**
- * Implementation of kernel_interface_t.destroy.
- */
-static void destroy(private_load_tester_ipsec_t *this)
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+ private_load_tester_ipsec_t *this, int fd, int family)
+{
+ return TRUE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+ private_load_tester_ipsec_t *this)
{
free(this);
}
@@ -155,21 +126,26 @@ static void destroy(private_load_tester_ipsec_t *this)
*/
load_tester_ipsec_t *load_tester_ipsec_create()
{
- private_load_tester_ipsec_t *this = malloc_thing(private_load_tester_ipsec_t);
-
- /* public functions */
- this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
- this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
- this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
- this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
- this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
- this->public.interface.add_policy = (status_t(*)(kernel_ipsec_t *this,host_t *, host_t *,traffic_selector_t *,traffic_selector_t *,policy_dir_t, u_int32_t,protocol_id_t, u_int32_t,ipsec_mode_t, u_int16_t, u_int16_t,bool))add_policy;
- this->public.interface.query_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
- this->public.interface.del_policy = (status_t(*)(kernel_ipsec_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,bool))del_policy;
- this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
-
- this->spi = 0;
+ private_load_tester_ipsec_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_spi = _get_spi,
+ .get_cpi = _get_cpi,
+ .add_sa = _add_sa,
+ .update_sa = _update_sa,
+ .query_sa = _query_sa,
+ .del_sa = _del_sa,
+ .add_policy = _add_policy,
+ .query_policy = _query_policy,
+ .del_policy = _del_policy,
+ .bypass_socket = _bypass_socket,
+ .destroy = _destroy,
+ },
+ },
+ .spi = 0,
+ );
return &this->public;
}
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index 46145b803..15dbccb00 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -158,7 +158,7 @@ static void destroy(private_load_tester_plugin_t *this)
charon->kernel_interface->remove_ipsec_interface(charon->kernel_interface,
(kernel_ipsec_constructor_t)load_tester_ipsec_create);
charon->backends->remove_backend(charon->backends, &this->config->backend);
- charon->credentials->remove_set(charon->credentials, &this->creds->credential_set);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set);
charon->bus->remove_listener(charon->bus, &this->listener->listener);
this->config->destroy(this->config);
this->creds->destroy(this->creds);
@@ -209,7 +209,7 @@ plugin_t *load_tester_plugin_create()
this->creds = load_tester_creds_create();
this->listener = load_tester_listener_create(shutdown_on);
charon->backends->add_backend(charon->backends, &this->config->backend);
- charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set);
charon->bus->add_listener(charon->bus, &this->listener->listener);
if (lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index 539890ec3..c26d325a9 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index e355d55f7..6cbaf36f2 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -181,8 +181,9 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
identification_create_from_encoding(ID_KEY_ID, other));
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
- child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE,
- MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0);
+ child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
@@ -260,7 +261,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->current->add_auth_cfg(this->current, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0);
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
diff --git a/src/libcharon/plugins/medcli/medcli_plugin.c b/src/libcharon/plugins/medcli/medcli_plugin.c
index 397168d46..6befbf440 100644
--- a/src/libcharon/plugins/medcli/medcli_plugin.c
+++ b/src/libcharon/plugins/medcli/medcli_plugin.c
@@ -61,7 +61,7 @@ static void destroy(private_medcli_plugin_t *this)
{
charon->bus->remove_listener(charon->bus, &this->listener->listener);
charon->backends->remove_backend(charon->backends, &this->config->backend);
- charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
this->listener->destroy(this->listener);
this->config->destroy(this->config);
this->creds->destroy(this->creds);
@@ -100,7 +100,7 @@ plugin_t *medcli_plugin_create()
this->config = medcli_config_create(this->db);
this->listener = medcli_listener_create(this->db);
- charon->credentials->add_set(charon->credentials, &this->creds->set);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
charon->bus->add_listener(charon->bus, &this->listener->listener);
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index a103a1340..4dc9c00d0 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.c b/src/libcharon/plugins/medsrv/medsrv_plugin.c
index 262d26d6b..c150346cb 100644
--- a/src/libcharon/plugins/medsrv/medsrv_plugin.c
+++ b/src/libcharon/plugins/medsrv/medsrv_plugin.c
@@ -54,7 +54,7 @@ struct private_medsrv_plugin_t {
static void destroy(private_medsrv_plugin_t *this)
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
- charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
this->config->destroy(this->config);
this->creds->destroy(this->creds);
this->db->destroy(this->db);
@@ -91,7 +91,7 @@ plugin_t *medsrv_plugin_create()
this->creds = medsrv_creds_create(this->db);
this->config = medsrv_config_create(this->db);
- charon->credentials->add_set(charon->credentials, &this->creds->set);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
return &this->public.plugin;
diff --git a/src/libcharon/plugins/nm/Makefile.in b/src/libcharon/plugins/nm/Makefile.in
index c7f288f54..1b3e4c5a6 100644
--- a/src/libcharon/plugins/nm/Makefile.in
+++ b/src/libcharon/plugins/nm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/nm/nm_plugin.c b/src/libcharon/plugins/nm/nm_plugin.c
index 6087f6589..250e6f7f9 100644
--- a/src/libcharon/plugins/nm/nm_plugin.c
+++ b/src/libcharon/plugins/nm/nm_plugin.c
@@ -84,7 +84,7 @@ static void destroy(private_nm_plugin_t *this)
{
g_object_unref(this->plugin);
}
- charon->credentials->remove_set(charon->credentials, &this->creds->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
this->creds->destroy(this->creds);
this->handler->destroy(this->handler);
@@ -110,7 +110,7 @@ plugin_t *nm_plugin_create()
this->creds = nm_creds_create();
this->handler = nm_handler_create();
hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
- charon->credentials->add_set(charon->credentials, &this->creds->set);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->set);
this->plugin = nm_strongswan_plugin_new(this->creds, this->handler);
if (!this->plugin)
{
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
index cdf7dc962..07318bbbf 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -444,7 +444,8 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg = child_cfg_create(priv->name, &lifetime,
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
- ACTION_NONE, ACTION_NONE, ipcomp, 0);
+ ACTION_NONE, ACTION_NONE, ipcomp, 0, 0,
+ NULL, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
diff --git a/src/libcharon/plugins/resolve/Makefile.am b/src/libcharon/plugins/resolve/Makefile.am
deleted file mode 100644
index f8830d42e..000000000
--- a/src/libcharon/plugins/resolve/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
- -I$(top_srcdir)/src/libcharon
-
-AM_CFLAGS = -rdynamic \
- -DRESOLV_CONF=\"${resolv_conf}\"
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-resolve.la
-else
-plugin_LTLIBRARIES = libstrongswan-resolve.la
-endif
-
-libstrongswan_resolve_la_SOURCES = \
- resolve_plugin.h resolve_plugin.c \
- resolve_handler.h resolve_handler.c
-
-libstrongswan_resolve_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/resolve/resolve_handler.c b/src/libcharon/plugins/resolve/resolve_handler.c
deleted file mode 100644
index 714c751a6..000000000
--- a/src/libcharon/plugins/resolve/resolve_handler.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "resolve_handler.h"
-
-#include <unistd.h>
-
-#include <daemon.h>
-#include <threading/mutex.h>
-
-typedef struct private_resolve_handler_t private_resolve_handler_t;
-
-/**
- * Private data of an resolve_handler_t object.
- */
-struct private_resolve_handler_t {
-
- /**
- * Public resolve_handler_t interface.
- */
- resolve_handler_t public;
-
- /**
- * resolv.conf file to use
- */
- char *file;
-
- /**
- * Mutex to access file exclusively
- */
- mutex_t *mutex;
-};
-
-/**
- * Implementation of attribute_handler_t.handle
- */
-static bool handle(private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
-{
- FILE *in, *out;
- char buf[1024];
- host_t *addr;
- size_t len;
- bool handled = FALSE;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- addr = host_create_from_chunk(AF_INET, data, 0);
- break;
- case INTERNAL_IP6_DNS:
- addr = host_create_from_chunk(AF_INET6, data, 0);
- break;
- default:
- return FALSE;
- }
-
- if (!addr || addr->is_anyaddr(addr))
- {
- DESTROY_IF(addr);
- return FALSE;
- }
- this->mutex->lock(this->mutex);
-
- in = fopen(this->file, "r");
- /* allows us to stream from in to out */
- unlink(this->file);
- out = fopen(this->file, "w");
- if (out)
- {
- fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server);
- DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file);
- handled = TRUE;
-
- /* copy rest of the file */
- if (in)
- {
- while ((len = fread(buf, 1, sizeof(buf), in)))
- {
- ignore_result(fwrite(buf, 1, len, out));
- }
- }
- fclose(out);
- }
- if (in)
- {
- fclose(in);
- }
- this->mutex->unlock(this->mutex);
- addr->destroy(addr);
-
- if (!handled)
- {
- DBG1(DBG_IKE, "adding DNS server failed", this->file);
- }
- return handled;
-}
-
-/**
- * Implementation of attribute_handler_t.release
- */
-static void release(private_resolve_handler_t *this, identification_t *server,
- configuration_attribute_type_t type, chunk_t data)
-{
- FILE *in, *out;
- char line[1024], matcher[512], *pos;
- host_t *addr;
- int family;
-
- switch (type)
- {
- case INTERNAL_IP4_DNS:
- family = AF_INET;
- break;
- case INTERNAL_IP6_DNS:
- family = AF_INET6;
- break;
- default:
- return;
- }
-
- this->mutex->lock(this->mutex);
-
- in = fopen(this->file, "r");
- if (in)
- {
- /* allows us to stream from in to out */
- unlink(this->file);
- out = fopen(this->file, "w");
- if (out)
- {
- addr = host_create_from_chunk(family, data, 0);
- snprintf(matcher, sizeof(matcher),
- "nameserver %H # by strongSwan, from %Y\n",
- addr, server);
-
- /* copy all, but matching line */
- while ((pos = fgets(line, sizeof(line), in)))
- {
- if (strneq(line, matcher, strlen(matcher)))
- {
- DBG1(DBG_IKE, "removing DNS server %H from %s",
- addr, this->file);
- }
- else
- {
- fputs(line, out);
- }
- }
- addr->destroy(addr);
- fclose(out);
- }
- fclose(in);
- }
-
- this->mutex->unlock(this->mutex);
-}
-
-/**
- * Attribute enumerator implementation
- */
-typedef struct {
- /** implements enumerator_t interface */
- enumerator_t public;
- /** virtual IP we are requesting */
- host_t *vip;
-} attribute_enumerator_t;
-
-/**
- * Implementation of create_attribute_enumerator().enumerate()
- */
-static bool attribute_enumerate(attribute_enumerator_t *this,
- configuration_attribute_type_t *type, chunk_t *data)
-{
- switch (this->vip->get_family(this->vip))
- {
- case AF_INET:
- *type = INTERNAL_IP4_DNS;
- break;
- case AF_INET6:
- *type = INTERNAL_IP6_DNS;
- break;
- default:
- return FALSE;
- }
- *data = chunk_empty;
- /* enumerate only once */
- this->public.enumerate = (void*)return_false;
- return TRUE;
-}
-
-/**
- * Implementation of attribute_handler_t.create_attribute_enumerator
- */
-static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this,
- identification_t *server, host_t *vip)
-{
- if (vip)
- {
- attribute_enumerator_t *enumerator;
-
- enumerator = malloc_thing(attribute_enumerator_t);
- enumerator->public.enumerate = (void*)attribute_enumerate;
- enumerator->public.destroy = (void*)free;
- enumerator->vip = vip;
-
- return &enumerator->public;
- }
- return enumerator_create_empty();
-}
-
-/**
- * Implementation of resolve_handler_t.destroy.
- */
-static void destroy(private_resolve_handler_t *this)
-{
- this->mutex->destroy(this->mutex);
- free(this);
-}
-
-/**
- * See header
- */
-resolve_handler_t *resolve_handler_create()
-{
- private_resolve_handler_t *this = malloc_thing(private_resolve_handler_t);
-
- this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
- this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
- this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
- this->public.destroy = (void(*)(resolve_handler_t*))destroy;
-
- this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
- this->file = lib->settings->get_str(lib->settings,
- "charon.plugins.resolve.file", RESOLV_CONF);
-
- return &this->public;
-}
-
diff --git a/src/libcharon/plugins/resolve/resolve_plugin.c b/src/libcharon/plugins/resolve/resolve_plugin.c
deleted file mode 100644
index 502129593..000000000
--- a/src/libcharon/plugins/resolve/resolve_plugin.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "resolve_plugin.h"
-#include "resolve_handler.h"
-
-#include <hydra.h>
-
-typedef struct private_resolve_plugin_t private_resolve_plugin_t;
-
-/**
- * private data of resolve plugin
- */
-struct private_resolve_plugin_t {
-
- /**
- * implements plugin interface
- */
- resolve_plugin_t public;
-
- /**
- * The registerd DNS attribute handler
- */
- resolve_handler_t *handler;
-};
-
-/**
- * Implementation of plugin_t.destroy
- */
-static void destroy(private_resolve_plugin_t *this)
-{
- hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
- this->handler->destroy(this->handler);
- free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *resolve_plugin_create()
-{
- private_resolve_plugin_t *this = malloc_thing(private_resolve_plugin_t);
-
- this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
- this->handler = resolve_handler_create();
- hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
-
- return &this->public.plugin;
-}
-
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index b88283f38..35fb8367f 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index 03c438acd..df63d862e 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index 3a5fb3778..8a3a15188 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/socket_raw/Makefile.in b/src/libcharon/plugins/socket_raw/Makefile.in
index 65ad6a7a9..32bd9e0a1 100644
--- a/src/libcharon/plugins/socket_raw/Makefile.in
+++ b/src/libcharon/plugins/socket_raw/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
index e0155fa87..166870421 100644
--- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c
+++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c
@@ -538,11 +538,12 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family)
/* Destination Port must be either port or natt_port */
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_UDP_PORT, 1, 0),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 5, 12),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IKEV2_NATT_PORT, 6, 14),
/* port */
- /* IKE version must be 2.0 */
+ /* IKE version must be 2.x */
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 10),
+ BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 11),
/* packet length is length in IKEv2 header + ip header + udp header */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + IKE_LENGTH_OFFSET),
BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN),
@@ -550,10 +551,11 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family)
/* natt_port */
/* nat-t: check for marker */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 5),
- /* nat-t: IKE version must be 2.0 */
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 6),
+ /* nat-t: IKE version must be 2.x */
BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + MARKER_LEN + IKE_VERSION_OFFSET),
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3),
+ BPF_STMT(BPF_ALU+BPF_RSH+BPF_K, 4),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 3),
/* nat-t: packet length is length in IKEv2 header + ip header + udp header + non esp marker */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + MARKER_LEN + IKE_LENGTH_OFFSET),
BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN + MARKER_LEN),
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 5803dc898..e32dc7b57 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 23366898a..a47d93f7b 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -134,7 +134,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
.time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
};
child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
- dpd, close, ipcomp, 0);
+ dpd, close, ipcomp, 0, 0, NULL, NULL);
/* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id);
diff --git a/src/libcharon/plugins/sql/sql_plugin.c b/src/libcharon/plugins/sql/sql_plugin.c
index e2d2d63b3..7b0a198d1 100644
--- a/src/libcharon/plugins/sql/sql_plugin.c
+++ b/src/libcharon/plugins/sql/sql_plugin.c
@@ -59,7 +59,7 @@ struct private_sql_plugin_t {
static void destroy(private_sql_plugin_t *this)
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
- charon->credentials->remove_set(charon->credentials, &this->cred->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->bus->remove_listener(charon->bus, &this->logger->listener);
this->config->destroy(this->config);
this->cred->destroy(this->cred);
@@ -99,7 +99,7 @@ plugin_t *sql_plugin_create()
this->logger = sql_logger_create(this->db);
charon->backends->add_backend(charon->backends, &this->config->backend);
- charon->credentials->add_set(charon->credentials, &this->cred->set);
+ lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->bus->add_listener(charon->bus, &this->logger->listener);
return &this->public.plugin;
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 8815ba741..e094200ca 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
index 49146f18b..9a3ae0ab9 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.c
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -306,7 +306,8 @@ static void del(private_stroke_ca_t *this, stroke_msg_t *msg)
return;
}
ca_section_destroy(ca);
- /* TODO: flush cached certs */
+
+ lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
}
/**
@@ -356,12 +357,16 @@ static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cer
{
if (section->certuribase && cert->issued_by(cert, section->cert))
{
- chunk_t hash, encoded = cert->get_encoding(cert);
- hasher->allocate_hash(hasher, encoded, &hash);
- section->hashes->insert_last(section->hashes,
- identification_create_from_encoding(ID_KEY_ID, hash));
- chunk_free(&hash);
- chunk_free(&encoded);
+ chunk_t hash, encoded;
+
+ if (cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
+ {
+ hasher->allocate_hash(hasher, encoded, &hash);
+ section->hashes->insert_last(section->hashes,
+ identification_create_from_encoding(ID_KEY_ID, hash));
+ chunk_free(&hash);
+ chunk_free(&encoded);
+ }
break;
}
}
@@ -400,11 +405,11 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out)
/* list authkey and keyid */
if (public)
{
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
{
fprintf(out, " authkey: %#B\n", &chunk);
}
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &chunk))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &chunk))
{
fprintf(out, " keyid: %#B\n", &chunk);
}
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index bbc1e7a31..617069432 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -399,8 +399,8 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
if (ca)
{
identity = identification_create_from_string(ca);
- certificate = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, identity, TRUE);
+ certificate = lib->credmgr->get_cert(lib->credmgr, CERT_X509,
+ KEY_ANY, identity, TRUE);
identity->destroy(identity);
if (certificate)
{
@@ -413,7 +413,7 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
}
}
- /* AC groups */
+ /* groups */
if (end->groups)
{
enumerator_t *enumerator;
@@ -422,9 +422,8 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
enumerator = enumerator_create_token(end->groups, ",", " ");
while (enumerator->enumerate(enumerator, &group))
{
- identity = identification_create_from_encoding(ID_IETF_ATTR_STRING,
- chunk_create(group, strlen(group)));
- cfg->add(cfg, AUTH_RULE_AC_GROUP, identity);
+ cfg->add(cfg, AUTH_RULE_GROUP,
+ identification_create_from_string(group));
}
enumerator->destroy(enumerator);
}
@@ -769,6 +768,14 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
.jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
}
};
+ mark_t mark_in = {
+ .value = msg->add_conn.mark_in.value,
+ .mask = msg->add_conn.mark_in.mask
+ };
+ mark_t mark_out = {
+ .value = msg->add_conn.mark_out.value,
+ .mask = msg->add_conn.mark_out.mask
+ };
switch (msg->add_conn.dpd.action)
{ /* map startes magic values to our action type */
@@ -787,7 +794,8 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
msg->add_conn.name, &lifetime,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp,
- msg->add_conn.inactivity);
+ msg->add_conn.inactivity, msg->add_conn.reqid,
+ &mark_in, &mark_out);
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index a03aef697..f64421551 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -186,6 +186,11 @@ static void terminate(private_stroke_control_t *this, stroke_msg_t *msg, FILE *o
}
else
{
+ if (!pos)
+ {
+ DBG1(DBG_CFG, "error parsing string");
+ return;
+ }
if (*(pos + 1) == '*')
{ /* is name[*] */
all = TRUE;
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index e0a5210a9..2816b9bb2 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -378,7 +378,7 @@ static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
}
if (found)
{
- new = cert->is_newer(cert, current);
+ new = crl_is_newer(crl, crl_c);
if (new)
{
this->certs->remove_at(this->certs, enumerator);
@@ -587,9 +587,11 @@ static void cache_cert(private_stroke_cred_t *this, certificate_t *cert)
snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex);
free(hex.ptr);
- chunk = cert->get_encoding(cert);
- chunk_write(chunk, buf, "crl", 022, TRUE);
- free(chunk.ptr);
+ if (cert->get_encoding(cert, CERT_ASN1_DER, &chunk))
+ {
+ chunk_write(chunk, buf, "crl", 022, TRUE);
+ free(chunk.ptr);
+ }
}
}
}
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index c2a98da33..a6de35466 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -17,6 +17,10 @@
#include <time.h>
+#ifdef HAVE_MALLINFO
+#include <malloc.h>
+#endif /* HAVE_MALLINFO */
+
#include <daemon.h>
#include <utils/linked_list.h>
#include <credentials/certificates/x509.h>
@@ -55,6 +59,33 @@ struct private_stroke_list_t {
};
/**
+ * Log tasks of a specific queue to out
+ */
+static void log_task_q(FILE *out, ike_sa_t *ike_sa, task_queue_t q, char *name)
+{
+ enumerator_t *enumerator;
+ bool has = FALSE;
+ task_t *task;
+
+ enumerator = ike_sa->create_task_enumerator(ike_sa, q);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (!has)
+ {
+ fprintf(out, "%12s[%d]: Tasks %s: ", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa), name);
+ has = TRUE;
+ }
+ fprintf(out, "%N ", task_type_names, task->get_type(task));
+ }
+ enumerator->destroy(enumerator);
+ if (has)
+ {
+ fprintf(out, "\n");
+ }
+}
+
+/**
* log an IKE_SA to out
*/
static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
@@ -140,6 +171,10 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
buf+4);
}
+
+ log_task_q(out, ike_sa, TASK_QUEUE_QUEUED, "queued");
+ log_task_q(out, ike_sa, TASK_QUEUE_ACTIVE, "active");
+ log_task_q(out, ike_sa, TASK_QUEUE_PASSIVE, "passive");
}
}
@@ -342,7 +377,7 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
rules = auth->create_enumerator(auth);
while (rules->enumerate(rules, &rule, &id))
{
- if (rule == AUTH_RULE_AC_GROUP)
+ if (rule == AUTH_RULE_GROUP)
{
fprintf(out, "%12s: group: %Y\n", name, id);
}
@@ -373,12 +408,19 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
u_int32_t dpd;
time_t since, now;
u_int size, online, offline;
-
now = time_monotonic(NULL);
since = time(NULL) - (now - this->uptime);
fprintf(out, "Status of IKEv2 charon daemon (strongSwan "VERSION"):\n");
fprintf(out, " uptime: %V, since %T\n", &now, &this->uptime, &since, FALSE);
+#ifdef HAVE_MALLINFO
+ {
+ struct mallinfo mi = mallinfo();
+
+ fprintf(out, " malloc: sbrk %d, mmap %d, used %d, free %d\n",
+ mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
+ }
+#endif /* HAVE_MALLINFO */
fprintf(out, " worker threads: %d idle of %d,",
charon->processor->get_idle_threads(charon->processor),
charon->processor->get_total_threads(charon->processor));
@@ -534,9 +576,8 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
static linked_list_t* create_unique_cert_list(certificate_type_t type)
{
linked_list_t *list = linked_list_create();
- enumerator_t *enumerator = charon->credentials->create_cert_enumerator(
- charon->credentials, type, KEY_ANY,
- NULL, FALSE);
+ enumerator_t *enumerator = lib->credmgr->create_cert_enumerator(
+ lib->credmgr, type, KEY_ANY, NULL, FALSE);
certificate_t *cert;
while (enumerator->enumerate(enumerator, (void**)&cert))
@@ -585,11 +626,11 @@ static void list_public_key(public_key_t *public, FILE *out)
identification_t *id;
auth_cfg_t *auth;
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
{
id = identification_create_from_encoding(ID_KEY_ID, keyid);
auth = auth_cfg_create();
- private = charon->credentials->get_private(charon->credentials,
+ private = lib->credmgr->get_private(lib->credmgr,
public->get_type(public), id, auth);
auth->destroy(auth);
id->destroy(id);
@@ -599,11 +640,11 @@ static void list_public_key(public_key_t *public, FILE *out)
key_type_names, public->get_type(public),
public->get_keysize(public) * 8,
private ? ", has private key" : "");
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
{
fprintf(out, " keyid: %#B\n", &keyid);
}
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
{
fprintf(out, " subjkey: %#B\n", &keyid);
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 56c18da38..18afa5af4 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -344,8 +344,7 @@ static void stroke_purge(private_stroke_socket_t *this,
{
if (msg->purge.flags & PURGE_OCSP)
{
- charon->credentials->flush_cache(charon->credentials,
- CERT_X509_OCSP_RESPONSE);
+ lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
}
if (msg->purge.flags & PURGE_IKE)
{
@@ -622,8 +621,8 @@ static bool open_socket(private_stroke_socket_t *this)
static void destroy(private_stroke_socket_t *this)
{
this->job->cancel(this->job);
- charon->credentials->remove_set(charon->credentials, &this->ca->set);
- charon->credentials->remove_set(charon->credentials, &this->cred->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
+ lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
charon->backends->remove_backend(charon->backends, &this->config->backend);
hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
this->cred->destroy(this->cred);
@@ -657,8 +656,8 @@ stroke_socket_t *stroke_socket_create()
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
- charon->credentials->add_set(charon->credentials, &this->ca->set);
- charon->credentials->add_set(charon->credentials, &this->cred->set);
+ lib->credmgr->add_set(lib->credmgr, &this->ca->set);
+ lib->credmgr->add_set(lib->credmgr, &this->cred->set);
charon->backends->add_backend(charon->backends, &this->config->backend);
hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index c10829bb3..934ab6080 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index bd58afbf0..ddddae782 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -196,7 +196,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0);
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0,
+ NULL, NULL);
child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
diff --git a/src/libcharon/plugins/uci/uci_plugin.c b/src/libcharon/plugins/uci/uci_plugin.c
index 742fcf4d0..4790ef4e7 100644
--- a/src/libcharon/plugins/uci/uci_plugin.c
+++ b/src/libcharon/plugins/uci/uci_plugin.c
@@ -64,7 +64,7 @@ struct private_uci_plugin_t {
static void destroy(private_uci_plugin_t *this)
{
charon->backends->remove_backend(charon->backends, &this->config->backend);
- charon->credentials->remove_set(charon->credentials, &this->creds->credential_set);
+ lib->credmgr->remove_set(lib->credmgr, &this->creds->credential_set);
this->config->destroy(this->config);
this->creds->destroy(this->creds);
this->parser->destroy(this->parser);
@@ -86,7 +86,7 @@ plugin_t *uci_plugin_create()
this->creds = uci_creds_create(this->parser);
this->control = uci_control_create();
charon->backends->add_backend(charon->backends, &this->config->backend);
- charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
+ lib->credmgr->add_set(lib->credmgr, &this->creds->credential_set);
return &this->public.plugin;
}
diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am
index e27d1f859..c46d2b85d 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.am
+++ b/src/libcharon/plugins/unit_tester/Makefile.am
@@ -24,6 +24,7 @@ libstrongswan_unit_tester_la_SOURCES = \
tests/test_chunk.c \
tests/test_pool.c \
tests/test_agent.c \
- tests/test_id.c
+ tests/test_id.c \
+ tests/test_hashtable.c
libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 6ca43a38f..47850c1c5 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -78,7 +78,7 @@ am_libstrongswan_unit_tester_la_OBJECTS = unit_tester.lo \
test_enumerator.lo test_auth_info.lo test_curl.lo \
test_mysql.lo test_sqlite.lo test_mutex.lo test_rsa_gen.lo \
test_cert.lo test_med_db.lo test_chunk.lo test_pool.lo \
- test_agent.lo test_id.lo
+ test_agent.lo test_id.lo test_hashtable.lo
libstrongswan_unit_tester_la_OBJECTS = \
$(am_libstrongswan_unit_tester_la_OBJECTS)
libstrongswan_unit_tester_la_LINK = $(LIBTOOL) --tag=CC \
@@ -281,7 +281,8 @@ libstrongswan_unit_tester_la_SOURCES = \
tests/test_chunk.c \
tests/test_pool.c \
tests/test_agent.c \
- tests/test_id.c
+ tests/test_id.c \
+ tests/test_hashtable.c
libstrongswan_unit_tester_la_LDFLAGS = -module -avoid-version
all: all-am
@@ -373,6 +374,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_chunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_curl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_enumerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_hashtable.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_id.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_med_db.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mutex.Plo@am__quote@
@@ -494,6 +496,13 @@ test_id.lo: tests/test_id.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_id.lo `test -f 'tests/test_id.c' || echo '$(srcdir)/'`tests/test_id.c
+test_hashtable.lo: tests/test_hashtable.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_hashtable.lo -MD -MP -MF $(DEPDIR)/test_hashtable.Tpo -c -o test_hashtable.lo `test -f 'tests/test_hashtable.c' || echo '$(srcdir)/'`tests/test_hashtable.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/test_hashtable.Tpo $(DEPDIR)/test_hashtable.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/test_hashtable.c' object='test_hashtable.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_hashtable.lo `test -f 'tests/test_hashtable.c' || echo '$(srcdir)/'`tests/test_hashtable.c
+
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/libcharon/plugins/unit_tester/tests.h b/src/libcharon/plugins/unit_tester/tests.h
index 96313d390..cd38c8a99 100644
--- a/src/libcharon/plugins/unit_tester/tests.h
+++ b/src/libcharon/plugins/unit_tester/tests.h
@@ -19,6 +19,7 @@
*/
DEFINE_TEST("linked_list_t->remove()", test_list_remove, FALSE)
+DEFINE_TEST("hashtable_t->remove_at()", test_hashtable_remove_at, FALSE)
DEFINE_TEST("simple enumerator", test_enumerate, FALSE)
DEFINE_TEST("nested enumerator", test_enumerate_nested, FALSE)
DEFINE_TEST("filtered enumerator", test_enumerate_filtered, FALSE)
diff --git a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c
index d6abe7a05..c250c356f 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_auth_info.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_auth_info.c
@@ -15,7 +15,7 @@
#include <daemon.h>
#include <library.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
static chunk_t certchunk = chunk_from_chars(
diff --git a/src/libcharon/plugins/unit_tester/tests/test_hashtable.c b/src/libcharon/plugins/unit_tester/tests/test_hashtable.c
new file mode 100644
index 000000000..bd79e12f7
--- /dev/null
+++ b/src/libcharon/plugins/unit_tester/tests/test_hashtable.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <utils/hashtable.h>
+
+static u_int hash(char *key)
+{
+ return chunk_hash(chunk_create(key, strlen(key)));
+}
+
+static u_int equals(char *key1, char *key2)
+{
+ return streq(key1, key2);
+}
+
+/**
+ * Test the remove_at method
+ */
+bool test_hashtable_remove_at()
+{
+ char *k1 = "key1", *k2 = "key2", *k3 = "key3", *key;
+ char *v1 = "val1", *v2 = "val2", *v3 = "val3", *value;
+ enumerator_t *enumerator;
+ hashtable_t *ht = hashtable_create((hashtable_hash_t)hash,
+ (hashtable_equals_t)equals, 0);
+
+ ht->put(ht, k1, v1);
+ ht->put(ht, k2, v2);
+ ht->put(ht, k3, v3);
+
+ if (ht->get_count(ht) != 3)
+ {
+ return FALSE;
+ }
+
+ enumerator = ht->create_enumerator(ht);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ if (streq(key, k2))
+ {
+ ht->remove_at(ht, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ht->get_count(ht) != 2)
+ {
+ return FALSE;
+ }
+
+ if (ht->get(ht, k1) == NULL ||
+ ht->get(ht, k3) == NULL)
+ {
+ return FALSE;
+ }
+
+ if (ht->get(ht, k2) != NULL)
+ {
+ return FALSE;
+ }
+
+ ht->put(ht, k2, v2);
+
+ if (ht->get_count(ht) != 3)
+ {
+ return FALSE;
+ }
+
+ if (ht->get(ht, k1) == NULL ||
+ ht->get(ht, k2) == NULL ||
+ ht->get(ht, k3) == NULL)
+ {
+ return FALSE;
+ }
+
+ enumerator = ht->create_enumerator(ht);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ ht->remove_at(ht, enumerator);
+ }
+ enumerator->destroy(enumerator);
+
+ if (ht->get_count(ht) != 0)
+ {
+ return FALSE;
+ }
+
+ if (ht->get(ht, k1) != NULL ||
+ ht->get(ht, k2) != NULL ||
+ ht->get(ht, k3) != NULL)
+ {
+ return FALSE;
+ }
+
+ ht->destroy(ht);
+
+ return TRUE;
+}
diff --git a/src/libcharon/plugins/unit_tester/tests/test_med_db.c b/src/libcharon/plugins/unit_tester/tests/test_med_db.c
index 7fd78b0bc..ae1d08e15 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_med_db.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_med_db.c
@@ -37,11 +37,11 @@ bool test_med_db()
bool good = FALSE;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, KEY_ANY, id, NULL);
+ enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
+ KEY_ANY, id, NULL);
while (enumerator->enumerate(enumerator, &public, &auth))
{
- good = public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &found);
+ good = public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &found);
if (good)
{
good = chunk_equals(id->get_encoding(id), found);
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index d3c509a32..ce233ad04 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 5a6746f92..ea4a792c2 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -115,7 +115,8 @@ METHOD(listener_t, child_updown, bool,
{
char command[1024];
char *my_client, *other_client, *my_client_mask, *other_client_mask;
- char *pos, *virtual_ip, *iface;
+ char *pos, *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc;
+ mark_t mark;
bool is_host, is_ipv6;
FILE *shell;
@@ -160,6 +161,61 @@ METHOD(listener_t, child_updown, bool,
}
}
+ /* check for the presence of an inbound mark */
+ mark = config->get_mark(config, TRUE);
+ if (mark.value)
+ {
+ if (asprintf(&mark_in, "PLUTO_MARK_IN='%u/0x%08x' ",
+ mark.value, mark.mask ) < 0)
+ {
+ mark_in = NULL;
+ }
+ }
+ else
+ {
+ if (asprintf(&mark_in, "") < 0)
+ {
+ mark_in = NULL;
+ }
+ }
+
+ /* check for the presence of an outbound mark */
+ mark = config->get_mark(config, FALSE);
+ if (mark.value)
+ {
+ if (asprintf(&mark_out, "PLUTO_MARK_OUT='%u/0x%08x' ",
+ mark.value, mark.mask ) < 0)
+ {
+ mark_out = NULL;
+ }
+ }
+ else
+ {
+ if (asprintf(&mark_out, "") < 0)
+ {
+ mark_out = NULL;
+ }
+ }
+
+ /* check for a NAT condition causing ESP_IN_UDP encapsulation */
+ if (ike_sa->has_condition(ike_sa, COND_NAT_ANY))
+ {
+ if (asprintf(&udp_enc, "PLUTO_UDP_ENC='%u' ",
+ other->get_port(other)) < 0)
+ {
+ udp_enc = NULL;
+ }
+
+ }
+ else
+ {
+ if (asprintf(&udp_enc, "") < 0)
+ {
+ udp_enc = NULL;
+ }
+
+ }
+
if (up)
{
iface = charon->kernel_interface->get_interface(
@@ -205,6 +261,9 @@ METHOD(listener_t, child_updown, bool,
"PLUTO_PEER_PROTOCOL='%u' "
"%s"
"%s"
+ "%s"
+ "%s"
+ "%s"
"%s",
up ? "up" : "down",
is_host ? "-host" : "-client",
@@ -223,11 +282,17 @@ METHOD(listener_t, child_updown, bool,
other_ts->get_from_port(other_ts),
other_ts->get_protocol(other_ts),
virtual_ip,
+ mark_in,
+ mark_out,
+ udp_enc,
config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
script);
free(my_client);
free(other_client);
free(virtual_ip);
+ free(mark_in);
+ free(mark_out);
+ free(udp_enc);
free(iface);
DBG3(DBG_CHD, "running updown script: %s", command);
@@ -283,7 +348,9 @@ updown_listener_t *updown_listener_create()
INIT(this,
.public = {
- .listener.child_updown = _child_updown,
+ .listener = {
+ .child_updown = _child_updown,
+ },
.destroy = _destroy,
},
.iface_cache = linked_list_create(),
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c
index 13586a23e..cd340e53e 100644
--- a/src/libcharon/sa/authenticators/authenticator.c
+++ b/src/libcharon/sa/authenticators/authenticator.c
@@ -34,13 +34,6 @@ ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS,
"ECDSA-521 signature");
ENUM_END(auth_method_names, AUTH_ECDSA_521);
-ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
- "any",
- "public key",
- "pre-shared key",
- "EAP",
-);
-
/**
* Described in header.
*/
diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h
index fff91ed34..89178b5cf 100644
--- a/src/libcharon/sa/authenticators/authenticator.h
+++ b/src/libcharon/sa/authenticators/authenticator.h
@@ -24,11 +24,10 @@
#define AUTHENTICATOR_H_
typedef enum auth_method_t auth_method_t;
-typedef enum auth_class_t auth_class_t;
typedef struct authenticator_t authenticator_t;
#include <library.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
#include <sa/ike_sa.h>
/**
@@ -76,27 +75,6 @@ enum auth_method_t {
extern enum_name_t *auth_method_names;
/**
- * Class of authentication to use. This is different to auth_method_t in that
- * it does not specify a method, but a class of acceptable methods. The found
- * certificate finally dictates wich method is used.
- */
-enum auth_class_t {
- /** any class acceptable */
- AUTH_CLASS_ANY = 0,
- /** authentication using public keys (RSA, ECDSA) */
- AUTH_CLASS_PUBKEY = 1,
- /** authentication using a pre-shared secrets */
- AUTH_CLASS_PSK = 2,
- /** authentication using EAP */
- AUTH_CLASS_EAP = 3,
-};
-
-/**
- * enum strings for auth_class_t
- */
-extern enum_name_t *auth_class_names;
-
-/**
* Authenticator interface implemented by the various authenticators.
*
* An authenticator implementation handles AUTH and EAP payloads. Received
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c
index 91fa5305f..ad7b92cfa 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.c
+++ b/src/libcharon/sa/authenticators/eap/eap_method.c
@@ -15,44 +15,6 @@
#include "eap_method.h"
-ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
- "EAP_IDENTITY",
- "EAP_NOTIFICATION",
- "EAP_NAK",
- "EAP_MD5",
- "EAP_OTP",
- "EAP_GTC");
-ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC,
- "EAP_SIM");
-ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
- "EAP_AKA");
-ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
- "EAP_MSCHAPV2");
-ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
- "EAP_RADIUS",
- "EAP_EXPANDED",
- "EAP_EXPERIMENTAL");
-ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
-
-ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
- "ID",
- "NTF",
- "NAK",
- "MD5",
- "OTP",
- "GTC");
-ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_GTC,
- "SIM");
-ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM,
- "AKA");
-ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
- "MSCHAPV2");
-ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
- "RAD",
- "EXP",
- "XP");
-ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
-
/*
* See header
*/
diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h
index 4cab84535..df354edb4 100644
--- a/src/libcharon/sa/authenticators/eap/eap_method.h
+++ b/src/libcharon/sa/authenticators/eap/eap_method.h
@@ -23,7 +23,6 @@
typedef struct eap_method_t eap_method_t;
typedef enum eap_role_t eap_role_t;
-typedef enum eap_type_t eap_type_t;
typedef enum eap_code_t eap_code_t;
#include <library.h>
@@ -43,35 +42,6 @@ enum eap_role_t {
extern enum_name_t *eap_role_names;
/**
- * EAP types, defines the EAP method implementation
- */
-enum eap_type_t {
- EAP_IDENTITY = 1,
- EAP_NOTIFICATION = 2,
- EAP_NAK = 3,
- EAP_MD5 = 4,
- EAP_OTP = 5,
- EAP_GTC = 6,
- EAP_SIM = 18,
- EAP_AKA = 23,
- EAP_MSCHAPV2 = 26,
- /** not a method, but an implementation providing different methods */
- EAP_RADIUS = 253,
- EAP_EXPANDED = 254,
- EAP_EXPERIMENTAL = 255,
-};
-
-/**
- * enum names for eap_type_t.
- */
-extern enum_name_t *eap_type_names;
-
-/**
- * short string enum names for eap_type_t.
- */
-extern enum_name_t *eap_type_short_names;
-
-/**
* Lookup the EAP method type from a string.
*
* @param name EAP method name (such as "md5", "aka")
diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c
index 4617c4d8d..3c0f3c358 100644
--- a/src/libcharon/sa/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/authenticators/eap_authenticator.c
@@ -140,17 +140,26 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
if (id)
{
- this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
- if (this->method)
+ if (id->get_type(id) == ID_ANY)
{
- if (this->method->initiate(this->method, &out) == NEED_MORE)
+ this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
+ if (this->method)
{
- DBG1(DBG_IKE, "initiating EAP-Identity request");
- return out;
+ if (this->method->initiate(this->method, &out) == NEED_MORE)
+ {
+ DBG1(DBG_IKE, "initiating EAP-Identity request");
+ return out;
+ }
+ this->method->destroy(this->method);
}
- this->method->destroy(this->method);
+ DBG1(DBG_IKE, "EAP-Identity request configured, "
+ "but not supported");
+ }
+ else
+ {
+ DBG1(DBG_IKE, "using configured EAP-Identity %Y", id);
+ this->eap_identity = id->clone(id);
}
- DBG1(DBG_IKE, "EAP-Identity request configured, but not supported");
}
}
/* invoke real EAP method */
@@ -220,7 +229,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
eap_type_t type, received_type;
u_int32_t vendor, received_vendor;
eap_payload_t *out;
- auth_cfg_t *cfg;
if (in->get_code(in) != EAP_RESPONSE)
{
@@ -283,12 +291,6 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
}
this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
TRUE);
- cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
- if (vendor)
- {
- cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
- }
this->eap_complete = TRUE;
return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
case FAILED:
diff --git a/src/libcharon/sa/authenticators/psk_authenticator.c b/src/libcharon/sa/authenticators/psk_authenticator.c
index 67197d690..e69f30dcf 100644
--- a/src/libcharon/sa/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/authenticators/psk_authenticator.c
@@ -63,8 +63,7 @@ static status_t build(private_psk_authenticator_t *this, message_t *message)
other_id = this->ike_sa->get_other_id(this->ike_sa);
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
my_id, auth_method_names, AUTH_PSK);
- key = charon->credentials->get_shared(charon->credentials, SHARED_IKE,
- my_id, other_id);
+ key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE, my_id, other_id);
if (key == NULL)
{
DBG1(DBG_IKE, "no shared key found for '%Y' - '%Y'", my_id, other_id);
@@ -107,8 +106,8 @@ static status_t process(private_psk_authenticator_t *this, message_t *message)
recv_auth_data = auth_payload->get_data(auth_payload);
my_id = this->ike_sa->get_my_id(this->ike_sa);
other_id = this->ike_sa->get_other_id(this->ike_sa);
- enumerator = charon->credentials->create_shared_enumerator(
- charon->credentials, SHARED_IKE, my_id, other_id);
+ enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
+ SHARED_IKE, my_id, other_id);
while (!authenticated && enumerator->enumerate(enumerator, &key, NULL, NULL))
{
keys_found++;
diff --git a/src/libcharon/sa/authenticators/pubkey_authenticator.c b/src/libcharon/sa/authenticators/pubkey_authenticator.c
index f1dca2702..3c67f6db6 100644
--- a/src/libcharon/sa/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/authenticators/pubkey_authenticator.c
@@ -65,8 +65,7 @@ static status_t build(private_pubkey_authenticator_t *this, message_t *message)
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
- private = charon->credentials->get_private(charon->credentials, KEY_ANY,
- id, auth);
+ private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
if (private == NULL)
{
DBG1(DBG_IKE, "no private key found for '%Y'", id);
@@ -178,8 +177,8 @@ static status_t process(private_pubkey_authenticator_t *this, message_t *message
octets = keymat->get_auth_octets(keymat, TRUE, this->ike_sa_init,
this->nonce, id);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
- enumerator = charon->credentials->create_public_enumerator(
- charon->credentials, key_type, id, auth);
+ enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
+ key_type, id, auth);
while (enumerator->enumerate(enumerator, &public, &current_auth))
{
if (public->verify(public, scheme, octets, auth_data))
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 3fdfb51ad..bd41cba56 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -98,6 +98,16 @@ struct private_child_sa_t {
u_int32_t reqid;
/**
+ * inbound mark used for this child_sa
+ */
+ mark_t mark_in;
+
+ /**
+ * outbound mark used for this child_sa
+ */
+ mark_t mark_out;
+
+ /**
* absolute time when rekeying is scheduled
*/
time_t rekey_time;
@@ -128,6 +138,16 @@ struct private_child_sa_t {
ipsec_mode_t mode;
/**
+ * Action to enforce if peer closes the CHILD_SA
+ */
+ action_t close_action;
+
+ /**
+ * Action to enforce if peer is considered dead
+ */
+ action_t dpd_action;
+
+ /**
* selected proposal
*/
proposal_t *proposal;
@@ -272,6 +292,38 @@ static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp)
}
/**
+ * Implementation of child_sa_t.set_close_action.
+ */
+static void set_close_action(private_child_sa_t *this, action_t action)
+{
+ this->close_action = action;
+}
+
+/**
+ * Implementation of child_sa_t.get_close_action.
+ */
+static action_t get_close_action(private_child_sa_t *this)
+{
+ return this->close_action;
+}
+
+/**
+ * Implementation of child_sa_t.set_dpd_action.
+ */
+static void set_dpd_action(private_child_sa_t *this, action_t action)
+{
+ this->dpd_action = action;
+}
+
+/**
+ * Implementation of child_sa_t.get_dpd_action.
+ */
+static action_t get_dpd_action(private_child_sa_t *this)
+{
+ return this->dpd_action;
+}
+
+/**
* Implementation of child_sa_t.get_proposal
*/
static proposal_t* get_proposal(private_child_sa_t *this)
@@ -389,10 +441,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->my_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->other_addr, this->my_addr,
- this->my_spi, this->protocol, &bytes);
+ this->my_spi, this->protocol,
+ this->mark_in, &bytes);
if (status == SUCCESS)
{
if (bytes > this->my_usebytes)
@@ -408,10 +460,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->other_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->my_addr, this->other_addr,
- this->other_spi, this->protocol, &bytes);
+ this->other_spi, this->protocol,
+ this->mark_out, &bytes);
if (status == SUCCESS)
{
if (bytes > this->other_usebytes)
@@ -443,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
if (inbound)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
+ other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
{
last_use = max(last_use, in);
}
if (this->mode != MODE_TRANSPORT)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
+ other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
{
last_use = max(last_use, fwd);
}
@@ -459,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
else
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
+ my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
{
last_use = max(last_use, out);
}
@@ -623,9 +675,10 @@ static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
}
status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, lifetime,
- enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
- this->encap, update, src_ts, dst_ts);
+ src, dst, spi, this->protocol, this->reqid,
+ inbound ? this->mark_in : this->mark_out,
+ lifetime, enc_alg, encr, int_alg, integ, this->mode,
+ this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
free(lifetime);
@@ -666,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->other_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->other_cpi, routed);
+ this->other_spi, this->protocol, this->reqid, this->mark_out,
+ this->mode, this->ipcomp, this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
if (this->mode != MODE_TRANSPORT)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
}
if (status != SUCCESS)
@@ -726,7 +779,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->my_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
this->other_addr, this->my_addr, other, me,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_in) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -739,7 +792,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->other_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
this->my_addr, this->other_addr, me, other,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_out) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -761,13 +814,13 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, FALSE);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, FALSE);
+ other_ts, my_ts, POLICY_IN, this->mark_in, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, FALSE);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE);
}
/* check whether we have to update a "dynamic" traffic selector */
@@ -793,18 +846,18 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->other_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_out, this->mode,
+ this->ipcomp, this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
}
}
enumerator->destroy(enumerator);
@@ -854,13 +907,13 @@ static void destroy(private_child_sa_t *this)
}
charon->kernel_interface->del_sa(charon->kernel_interface,
this->other_addr, this->my_addr, this->my_spi,
- this->protocol, this->my_cpi);
+ this->protocol, this->my_cpi, this->mark_in);
}
if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
this->my_addr, this->other_addr, this->other_spi,
- this->protocol, this->other_cpi);
+ this->protocol, this->other_cpi, this->mark_out);
}
if (this->config->install_policy(this->config))
@@ -870,13 +923,13 @@ static void destroy(private_child_sa_t *this)
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, unrouted);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, unrouted);
+ other_ts, my_ts, POLICY_IN, this->mark_in, unrouted);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, unrouted);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted);
}
}
enumerator->destroy(enumerator);
@@ -919,6 +972,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
+ this->public.get_close_action = (action_t(*)(child_sa_t*))get_close_action;
+ this->public.set_close_action = (void(*)(child_sa_t*,action_t))set_close_action;
+ this->public.get_dpd_action = (action_t(*)(child_sa_t*))get_dpd_action;
+ this->public.set_dpd_action = (void(*)(child_sa_t*,action_t))set_dpd_action;
this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install;
@@ -942,17 +999,26 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->other_usetime = 0;
this->my_usebytes = 0;
this->other_usebytes = 0;
- /* reuse old reqid if we are rekeying an existing CHILD_SA */
- this->reqid = rekey ? rekey : ++reqid;
this->my_ts = linked_list_create();
this->other_ts = linked_list_create();
this->protocol = PROTO_NONE;
this->mode = MODE_TUNNEL;
+ this->close_action = config->get_close_action(config);
+ this->dpd_action = config->get_dpd_action(config);
this->proposal = NULL;
this->rekey_time = 0;
this->expire_time = 0;
this->config = config;
config->get_ref(config);
+ this->reqid = config->get_reqid(config);
+ this->mark_in = config->get_mark(config, TRUE);
+ this->mark_out = config->get_mark(config, FALSE);
+
+ if (!this->reqid)
+ {
+ /* reuse old reqid if we are rekeying an existing CHILD_SA */
+ this->reqid = rekey ? rekey : ++reqid;
+ }
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index e6c603504..95bc297b0 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -208,6 +208,34 @@ struct child_sa_t {
void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
/**
+ * Get the action to enforce if the remote peer closes the CHILD_SA.
+ *
+ * @return close action
+ */
+ action_t (*get_close_action)(child_sa_t *this);
+
+ /**
+ * Override the close action specified by the CHILD_SA config.
+ *
+ * @param close action to enforce
+ */
+ void (*set_close_action)(child_sa_t *this, action_t action);
+
+ /**
+ * Get the action to enforce if the peer is considered dead.
+ *
+ * @return dpd action
+ */
+ action_t (*get_dpd_action)(child_sa_t *this);
+
+ /**
+ * Override the DPD action specified by the CHILD_SA config.
+ *
+ * @param close action to enforce
+ */
+ void (*set_dpd_action)(child_sa_t *this, action_t action);
+
+ /**
* Get the selected proposal.
*
* @return selected proposal
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 023f0749f..7536662ca 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -287,18 +287,14 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
return use_time;
}
-/**
- * Implementation of ike_sa_t.get_unique_id
- */
-static u_int32_t get_unique_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_unique_id, u_int32_t,
+ private_ike_sa_t *this)
{
return this->unique_id;
}
-/**
- * Implementation of ike_sa_t.get_name.
- */
-static char *get_name(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_name, char*,
+ private_ike_sa_t *this)
{
if (this->peer_cfg)
{
@@ -307,10 +303,8 @@ static char *get_name(private_ike_sa_t *this)
return "(unnamed)";
}
-/**
- * Implementation of ike_sa_t.get_statistic.
- */
-static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
+METHOD(ike_sa_t, get_statistic, u_int32_t,
+ private_ike_sa_t *this, statistic_t kind)
{
if (kind < STAT_MAX)
{
@@ -319,52 +313,40 @@ static u_int32_t get_statistic(private_ike_sa_t *this, statistic_t kind)
return 0;
}
-/**
- * Implementation of ike_sa_t.get_my_host.
- */
-static host_t *get_my_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_my_host, host_t*,
+ private_ike_sa_t *this)
{
return this->my_host;
}
-/**
- * Implementation of ike_sa_t.set_my_host.
- */
-static void set_my_host(private_ike_sa_t *this, host_t *me)
+METHOD(ike_sa_t, set_my_host, void,
+ private_ike_sa_t *this, host_t *me)
{
DESTROY_IF(this->my_host);
this->my_host = me;
}
-/**
- * Implementation of ike_sa_t.get_other_host.
- */
-static host_t *get_other_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_host, host_t*,
+ private_ike_sa_t *this)
{
return this->other_host;
}
-/**
- * Implementation of ike_sa_t.set_other_host.
- */
-static void set_other_host(private_ike_sa_t *this, host_t *other)
+METHOD(ike_sa_t, set_other_host, void,
+ private_ike_sa_t *this, host_t *other)
{
DESTROY_IF(this->other_host);
this->other_host = other;
}
-/**
- * Implementation of ike_sa_t.get_peer_cfg
- */
-static peer_cfg_t* get_peer_cfg(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_peer_cfg, peer_cfg_t*,
+ private_ike_sa_t *this)
{
return this->peer_cfg;
}
-/**
- * Implementation of ike_sa_t.set_peer_cfg
- */
-static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
+METHOD(ike_sa_t, set_peer_cfg, void,
+ private_ike_sa_t *this, peer_cfg_t *peer_cfg)
{
DESTROY_IF(this->peer_cfg);
peer_cfg->get_ref(peer_cfg);
@@ -377,10 +359,8 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
}
}
-/**
- * Implementation of ike_sa_t.get_auth_cfg
- */
-static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
+METHOD(ike_sa_t, get_auth_cfg, auth_cfg_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -389,10 +369,8 @@ static auth_cfg_t* get_auth_cfg(private_ike_sa_t *this, bool local)
return this->other_auth;
}
-/**
- * Implementation of ike_sa_t.add_auth_cfg
- */
-static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
+METHOD(ike_sa_t, add_auth_cfg, void,
+ private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
{
if (local)
{
@@ -404,11 +382,8 @@ static void add_auth_cfg(private_ike_sa_t *this, bool local, auth_cfg_t *cfg)
}
}
-/**
- * Implementation of ike_sa_t.create_auth_cfg_enumerator
- */
-static enumerator_t* create_auth_cfg_enumerator(private_ike_sa_t *this,
- bool local)
+METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -424,42 +399,33 @@ static void flush_auth_cfgs(private_ike_sa_t *this)
{
auth_cfg_t *cfg;
- if (lib->settings->get_bool(lib->settings, "charon.flush_auth_cfg", FALSE))
+ while (this->my_auths->remove_last(this->my_auths,
+ (void**)&cfg) == SUCCESS)
{
- while (this->my_auths->remove_last(this->my_auths,
- (void**)&cfg) == SUCCESS)
- {
- cfg->destroy(cfg);
- }
- while (this->other_auths->remove_last(this->other_auths,
- (void**)&cfg) == SUCCESS)
- {
- cfg->destroy(cfg);
- }
+ cfg->destroy(cfg);
+ }
+ while (this->other_auths->remove_last(this->other_auths,
+ (void**)&cfg) == SUCCESS)
+ {
+ cfg->destroy(cfg);
}
}
-/**
- * Implementation of ike_sa_t.get_proposal
- */
-static proposal_t* get_proposal(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_proposal, proposal_t*,
+ private_ike_sa_t *this)
{
return this->proposal;
}
-/**
- * Implementation of ike_sa_t.set_proposal
- */
-static void set_proposal(private_ike_sa_t *this, proposal_t *proposal)
+METHOD(ike_sa_t, set_proposal, void,
+ private_ike_sa_t *this, proposal_t *proposal)
{
DESTROY_IF(this->proposal);
this->proposal = proposal->clone(proposal);
}
-/**
- * Implementation of ike_sa_t.set_message_id
- */
-static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid)
+METHOD(ike_sa_t, set_message_id, void,
+ private_ike_sa_t *this, bool initiate, u_int32_t mid)
{
if (initiate)
{
@@ -471,10 +437,8 @@ static void set_message_id(private_ike_sa_t *this, bool initiate, u_int32_t mid)
}
}
-/**
- * Implementation of ike_sa_t.send_keepalive
- */
-static void send_keepalive(private_ike_sa_t *this)
+METHOD(ike_sa_t, send_keepalive, void,
+ private_ike_sa_t *this)
{
send_keepalive_job_t *job;
time_t last_out, now, diff;
@@ -510,52 +474,39 @@ static void send_keepalive(private_ike_sa_t *this)
this->keepalive_interval - diff);
}
-/**
- * Implementation of ike_sa_t.get_ike_cfg
- */
-static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_ike_cfg, ike_cfg_t*,
+ private_ike_sa_t *this)
{
return this->ike_cfg;
}
-/**
- * Implementation of ike_sa_t.set_ike_cfg
- */
-static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg)
+METHOD(ike_sa_t, set_ike_cfg, void,
+ private_ike_sa_t *this, ike_cfg_t *ike_cfg)
{
ike_cfg->get_ref(ike_cfg);
this->ike_cfg = ike_cfg;
}
-/**
- * Implementation of ike_sa_t.enable_extension.
- */
-static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
+METHOD(ike_sa_t, enable_extension, void,
+ private_ike_sa_t *this, ike_extension_t extension)
{
this->extensions |= extension;
}
-/**
- * Implementation of ike_sa_t.has_extension.
- */
-static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
+METHOD(ike_sa_t, supports_extension, bool,
+ private_ike_sa_t *this, ike_extension_t extension)
{
return (this->extensions & extension) != FALSE;
}
-/**
- * Implementation of ike_sa_t.has_condition.
- */
-static bool has_condition(private_ike_sa_t *this, ike_condition_t condition)
+METHOD(ike_sa_t, has_condition, bool,
+ private_ike_sa_t *this, ike_condition_t condition)
{
return (this->conditions & condition) != FALSE;
}
-/**
- * Implementation of ike_sa_t.enable_condition.
- */
-static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
- bool enable)
+METHOD(ike_sa_t, set_condition, void,
+ private_ike_sa_t *this, ike_condition_t condition, bool enable)
{
if (has_condition(this, condition) != enable)
{
@@ -601,10 +552,8 @@ static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
}
}
-/**
- * Implementation of ike_sa_t.send_dpd
- */
-static status_t send_dpd(private_ike_sa_t *this)
+METHOD(ike_sa_t, send_dpd, status_t,
+ private_ike_sa_t *this)
{
job_t *job;
time_t diff, delay;
@@ -660,18 +609,14 @@ static status_t send_dpd(private_ike_sa_t *this)
return SUCCESS;
}
-/**
- * Implementation of ike_sa_t.get_state.
- */
-static ike_sa_state_t get_state(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_state, ike_sa_state_t,
+ private_ike_sa_t *this)
{
return this->state;
}
-/**
- * Implementation of ike_sa_t.set_state.
- */
-static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
+METHOD(ike_sa_t, set_state, void,
+ private_ike_sa_t *this, ike_sa_state_t state)
{
DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
get_name(this), this->unique_id,
@@ -754,10 +699,8 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
this->state = state;
}
-/**
- * Implementation of ike_sa_t.reset
- */
-static void reset(private_ike_sa_t *this)
+METHOD(ike_sa_t, reset, void,
+ private_ike_sa_t *this)
{
/* the responder ID is reset, as peer may choose another one */
if (this->ike_sa_id->is_initiator(this->ike_sa_id))
@@ -767,21 +710,22 @@ static void reset(private_ike_sa_t *this)
set_state(this, IKE_CREATED);
+ flush_auth_cfgs(this);
+
+ this->keymat->destroy(this->keymat);
+ this->keymat = keymat_create(this->ike_sa_id->is_initiator(this->ike_sa_id));
+
this->task_manager->reset(this->task_manager, 0, 0);
}
-/**
- * Implementation of ike_sa_t.get_keymat
- */
-static keymat_t* get_keymat(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_keymat, keymat_t*,
+ private_ike_sa_t *this)
{
return this->keymat;
}
-/**
- * Implementation of ike_sa_t.set_virtual_ip
- */
-static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
+METHOD(ike_sa_t, set_virtual_ip, void,
+ private_ike_sa_t *this, bool local, host_t *ip)
{
if (local)
{
@@ -811,10 +755,8 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
}
}
-/**
- * Implementation of ike_sa_t.get_virtual_ip
- */
-static host_t* get_virtual_ip(private_ike_sa_t *this, bool local)
+METHOD(ike_sa_t, get_virtual_ip, host_t*,
+ private_ike_sa_t *this, bool local)
{
if (local)
{
@@ -826,27 +768,21 @@ static host_t* get_virtual_ip(private_ike_sa_t *this, bool local)
}
}
-/**
- * Implementation of ike_sa_t.add_additional_address.
- */
-static void add_additional_address(private_ike_sa_t *this, host_t *host)
+METHOD(ike_sa_t, add_additional_address, void,
+ private_ike_sa_t *this, host_t *host)
{
this->additional_addresses->insert_last(this->additional_addresses, host);
}
-/**
- * Implementation of ike_sa_t.create_additional_address_iterator.
- */
-static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
+METHOD(ike_sa_t, create_additional_address_iterator, iterator_t*,
+ private_ike_sa_t *this)
{
return this->additional_addresses->create_iterator(
this->additional_addresses, TRUE);
}
-/**
- * Implementation of ike_sa_t.has_mapping_changed
- */
-static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
+METHOD(ike_sa_t, has_mapping_changed, bool,
+ private_ike_sa_t *this, chunk_t hash)
{
if (this->nat_detection_dest.ptr == NULL)
{
@@ -862,26 +798,20 @@ static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash)
return TRUE;
}
-/**
- * Implementation of ike_sa_t.set_pending_updates.
- */
-static void set_pending_updates(private_ike_sa_t *this, u_int32_t updates)
+METHOD(ike_sa_t, set_pending_updates, void,
+ private_ike_sa_t *this, u_int32_t updates)
{
this->pending_updates = updates;
}
-/**
- * Implementation of ike_sa_t.get_pending_updates.
- */
-static u_int32_t get_pending_updates(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_pending_updates, u_int32_t,
+ private_ike_sa_t *this)
{
return this->pending_updates;
}
-/**
- * Update hosts, as addresses may change (NAT)
- */
-static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
+METHOD(ike_sa_t, update_hosts, void,
+ private_ike_sa_t *this, host_t *me, host_t *other)
{
bool update = FALSE;
@@ -946,11 +876,8 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
}
}
-/**
- * Implementation of ike_sa_t.generate
- */
-static status_t generate_message(private_ike_sa_t *this, message_t *message,
- packet_t **packet)
+METHOD(ike_sa_t, generate_message, status_t,
+ private_ike_sa_t *this, message_t *message, packet_t **packet)
{
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
message->set_ike_sa_id(message, this->ike_sa_id);
@@ -994,10 +921,8 @@ static void send_notify_response(private_ike_sa_t *this, message_t *request,
response->destroy(response);
}
-/**
- * Implementation of ike_sa_t.set_kmaddress.
- */
-static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
+METHOD(ike_sa_t, set_kmaddress, void,
+ private_ike_sa_t *this, host_t *local, host_t *remote)
{
DESTROY_IF(this->local_host);
DESTROY_IF(this->remote_host);
@@ -1006,46 +931,35 @@ static void set_kmaddress(private_ike_sa_t *this, host_t *local, host_t *remote)
}
#ifdef ME
-/**
- * Implementation of ike_sa_t.act_as_mediation_server.
- */
-static void act_as_mediation_server(private_ike_sa_t *this)
+METHOD(ike_sa_t, act_as_mediation_server, void,
+ private_ike_sa_t *this)
{
charon->mediation_manager->update_sa_id(charon->mediation_manager,
this->other_id, this->ike_sa_id);
this->is_mediation_server = TRUE;
}
-/**
- * Implementation of ike_sa_t.get_server_reflexive_host.
- */
-static host_t *get_server_reflexive_host(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_server_reflexive_host, host_t*,
+ private_ike_sa_t *this)
{
return this->server_reflexive_host;
}
-/**
- * Implementation of ike_sa_t.set_server_reflexive_host.
- */
-static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host)
+METHOD(ike_sa_t, set_server_reflexive_host, void,
+ private_ike_sa_t *this, host_t *host)
{
DESTROY_IF(this->server_reflexive_host);
this->server_reflexive_host = host;
}
-/**
- * Implementation of ike_sa_t.get_connect_id.
- */
-static chunk_t get_connect_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_connect_id, chunk_t,
+ private_ike_sa_t *this)
{
return this->connect_id;
}
-/**
- * Implementation of ike_sa_t.respond
- */
-static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
- chunk_t connect_id)
+METHOD(ike_sa_t, respond, status_t,
+ private_ike_sa_t *this, identification_t *peer_id, chunk_t connect_id)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->respond(task, peer_id, connect_id);
@@ -1053,10 +967,8 @@ static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.callback
- */
-static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
+METHOD(ike_sa_t, callback, status_t,
+ private_ike_sa_t *this, identification_t *peer_id)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->callback(task, peer_id);
@@ -1064,12 +976,9 @@ static status_t callback(private_ike_sa_t *this, identification_t *peer_id)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.relay
- */
-static status_t relay(private_ike_sa_t *this, identification_t *requester,
- chunk_t connect_id, chunk_t connect_key,
- linked_list_t *endpoints, bool response)
+METHOD(ike_sa_t, relay, status_t,
+ private_ike_sa_t *this, identification_t *requester, chunk_t connect_id,
+ chunk_t connect_key, linked_list_t *endpoints, bool response)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->relay(task, requester, connect_id, connect_key, endpoints, response);
@@ -1077,11 +986,8 @@ static status_t relay(private_ike_sa_t *this, identification_t *requester,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.initiate_mediation
- */
-static status_t initiate_mediation(private_ike_sa_t *this,
- peer_cfg_t *mediated_cfg)
+METHOD(ike_sa_t, initiate_mediation, status_t,
+ private_ike_sa_t *this, peer_cfg_t *mediated_cfg)
{
ike_me_t *task = ike_me_create(&this->public, TRUE);
task->connect(task, mediated_cfg->get_peer_id(mediated_cfg));
@@ -1089,11 +995,8 @@ static status_t initiate_mediation(private_ike_sa_t *this,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.initiate_mediated
- */
-static status_t initiate_mediated(private_ike_sa_t *this, host_t *me,
- host_t *other, chunk_t connect_id)
+METHOD(ike_sa_t, initiate_mediated, status_t,
+ private_ike_sa_t *this, host_t *me, host_t *other, chunk_t connect_id)
{
set_my_host(this, me->clone(me));
set_other_host(this, other->clone(other));
@@ -1166,12 +1069,9 @@ static void resolve_hosts(private_ike_sa_t *this)
}
}
-/**
- * Implementation of ike_sa_t.initiate
- */
-static status_t initiate(private_ike_sa_t *this,
- child_cfg_t *child_cfg, u_int32_t reqid,
- traffic_selector_t *tsi, traffic_selector_t *tsr)
+METHOD(ike_sa_t, initiate, status_t,
+ private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid,
+ traffic_selector_t *tsi, traffic_selector_t *tsr)
{
task_t *task;
@@ -1259,10 +1159,8 @@ static status_t initiate(private_ike_sa_t *this,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.process_message.
- */
-static status_t process_message(private_ike_sa_t *this, message_t *message)
+METHOD(ike_sa_t, process_message, status_t,
+ private_ike_sa_t *this, message_t *message)
{
status_t status;
bool is_request;
@@ -1367,7 +1265,9 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
}
status = this->task_manager->process_message(this->task_manager, message);
if (message->get_exchange_type(message) == IKE_AUTH &&
- this->state == IKE_ESTABLISHED)
+ this->state == IKE_ESTABLISHED &&
+ lib->settings->get_bool(lib->settings,
+ "charon.flush_auth_cfg", FALSE))
{ /* authentication completed */
flush_auth_cfgs(this);
}
@@ -1375,43 +1275,33 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
return status;
}
-/**
- * Implementation of ike_sa_t.get_id.
- */
-static ike_sa_id_t* get_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_id, ike_sa_id_t*,
+ private_ike_sa_t *this)
{
return this->ike_sa_id;
}
-/**
- * Implementation of ike_sa_t.get_my_id.
- */
-static identification_t* get_my_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_my_id, identification_t*,
+ private_ike_sa_t *this)
{
return this->my_id;
}
-/**
- * Implementation of ike_sa_t.set_my_id.
- */
-static void set_my_id(private_ike_sa_t *this, identification_t *me)
+METHOD(ike_sa_t, set_my_id, void,
+ private_ike_sa_t *this, identification_t *me)
{
DESTROY_IF(this->my_id);
this->my_id = me;
}
-/**
- * Implementation of ike_sa_t.get_other_id.
- */
-static identification_t* get_other_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_id, identification_t*,
+ private_ike_sa_t *this)
{
return this->other_id;
}
-/**
- * Implementation of ike_sa_t.get_other_eap_id.
- */
-static identification_t* get_other_eap_id(private_ike_sa_t *this)
+METHOD(ike_sa_t, get_other_eap_id, identification_t*,
+ private_ike_sa_t *this)
{
identification_t *id = NULL, *current;
enumerator_t *enumerator;
@@ -1440,28 +1330,21 @@ static identification_t* get_other_eap_id(private_ike_sa_t *this)
return this->other_id;
}
-/**
- * Implementation of ike_sa_t.set_other_id.
- */
-static void set_other_id(private_ike_sa_t *this, identification_t *other)
+METHOD(ike_sa_t, set_other_id, void,
+ private_ike_sa_t *this, identification_t *other)
{
DESTROY_IF(this->other_id);
this->other_id = other;
}
-/**
- * Implementation of ike_sa_t.add_child_sa.
- */
-static void add_child_sa(private_ike_sa_t *this, child_sa_t *child_sa)
+METHOD(ike_sa_t, add_child_sa, void,
+ private_ike_sa_t *this, child_sa_t *child_sa)
{
this->child_sas->insert_last(this->child_sas, child_sa);
}
-/**
- * Implementation of ike_sa_t.get_child_sa.
- */
-static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi, bool inbound)
+METHOD(ike_sa_t, get_child_sa, child_sa_t*,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi, bool inbound)
{
iterator_t *iterator;
child_sa_t *current, *found = NULL;
@@ -1479,19 +1362,14 @@ static child_sa_t* get_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return found;
}
-/**
- * Implementation of ike_sa_t.create_child_sa_iterator.
- */
-static iterator_t* create_child_sa_iterator(private_ike_sa_t *this)
+METHOD(ike_sa_t, create_child_sa_iterator, iterator_t*,
+ private_ike_sa_t *this)
{
return this->child_sas->create_iterator(this->child_sas, TRUE);
}
-/**
- * Implementation of ike_sa_t.rekey_child_sa.
- */
-static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, rekey_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
child_rekey_t *child_rekey;
@@ -1500,11 +1378,8 @@ static status_t rekey_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.delete_child_sa.
- */
-static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, delete_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
child_delete_t *child_delete;
@@ -1513,11 +1388,8 @@ static status_t delete_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.destroy_child_sa.
- */
-static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
- u_int32_t spi)
+METHOD(ike_sa_t, destroy_child_sa, status_t,
+ private_ike_sa_t *this, protocol_id_t protocol, u_int32_t spi)
{
iterator_t *iterator;
child_sa_t *child_sa;
@@ -1539,10 +1411,8 @@ static status_t destroy_child_sa(private_ike_sa_t *this, protocol_id_t protocol,
return status;
}
-/**
- * Implementation of public_ike_sa_t.delete.
- */
-static status_t delete_(private_ike_sa_t *this)
+METHOD(ike_sa_t, delete_, status_t,
+ private_ike_sa_t *this)
{
ike_delete_t *ike_delete;
@@ -1567,10 +1437,8 @@ static status_t delete_(private_ike_sa_t *this)
return DESTROY_ME;
}
-/**
- * Implementation of ike_sa_t.rekey.
- */
-static status_t rekey(private_ike_sa_t *this)
+METHOD(ike_sa_t, rekey, status_t,
+ private_ike_sa_t *this)
{
ike_rekey_t *ike_rekey;
@@ -1580,10 +1448,8 @@ static status_t rekey(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.reauth
- */
-static status_t reauth(private_ike_sa_t *this)
+METHOD(ike_sa_t, reauth, status_t,
+ private_ike_sa_t *this)
{
task_t *task;
@@ -1618,10 +1484,8 @@ static status_t reauth(private_ike_sa_t *this)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.reestablish
- */
-static status_t reestablish(private_ike_sa_t *this)
+METHOD(ike_sa_t, reestablish, status_t,
+ private_ike_sa_t *this)
{
ike_sa_t *new;
host_t *host;
@@ -1636,14 +1500,13 @@ static status_t reestablish(private_ike_sa_t *this)
iterator = create_child_sa_iterator(this);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_cfg = child_sa->get_config(child_sa);
if (this->state == IKE_DELETING)
{
- action = child_cfg->get_close_action(child_cfg);
+ action = child_sa->get_close_action(child_sa);
}
else
{
- action = child_cfg->get_dpd_action(child_cfg);
+ action = child_sa->get_dpd_action(child_sa);
}
switch (action)
{
@@ -1651,7 +1514,8 @@ static status_t reestablish(private_ike_sa_t *this)
restart = TRUE;
break;
case ACTION_ROUTE:
- charon->traps->install(charon->traps, this->peer_cfg, child_cfg);
+ charon->traps->install(charon->traps, this->peer_cfg,
+ child_sa->get_config(child_sa));
break;
default:
break;
@@ -1707,18 +1571,18 @@ static status_t reestablish(private_ike_sa_t *this)
iterator = create_child_sa_iterator(this);
while (iterator->iterate(iterator, (void**)&child_sa))
{
- child_cfg = child_sa->get_config(child_sa);
if (this->state == IKE_DELETING)
{
- action = child_cfg->get_close_action(child_cfg);
+ action = child_sa->get_close_action(child_sa);
}
else
{
- action = child_cfg->get_dpd_action(child_cfg);
+ action = child_sa->get_dpd_action(child_sa);
}
switch (action)
{
case ACTION_RESTART:
+ child_cfg = child_sa->get_config(child_sa);
DBG1(DBG_IKE, "restarting CHILD_SA %s",
child_cfg->get_name(child_cfg));
child_cfg->get_ref(child_cfg);
@@ -1750,9 +1614,41 @@ static status_t reestablish(private_ike_sa_t *this)
}
/**
- * Implementation of ike_sa_t.retransmit.
+ * Requeue the IKE_SA_INIT tasks for initiation, if required
*/
-static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
+static void requeue_init_tasks(private_ike_sa_t *this)
+{
+ enumerator_t *enumerator;
+ bool has_init = FALSE;
+ task_t *task;
+
+ /* if we have advanced to IKE_AUTH, the IKE_INIT and related tasks
+ * have already completed. Recreate them if necessary. */
+ enumerator = this->task_manager->create_task_enumerator(
+ this->task_manager, TASK_QUEUE_QUEUED);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == IKE_INIT)
+ {
+ has_init = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!has_init)
+ {
+ task = (task_t*)ike_vendor_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_natd_create(&this->public, TRUE);
+ this->task_manager->queue_task(this->task_manager, task);
+ task = (task_t*)ike_init_create(&this->public, TRUE, NULL);
+ this->task_manager->queue_task(this->task_manager, task);
+ }
+}
+
+METHOD(ike_sa_t, retransmit, status_t,
+ private_ike_sa_t *this, u_int32_t message_id)
{
this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS)
@@ -1770,6 +1666,7 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
this->keyingtry + 1, tries);
reset(this);
+ requeue_init_tasks(this);
return this->task_manager->initiate(this->task_manager);
}
DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
@@ -1790,10 +1687,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
return SUCCESS;
}
-/**
- * Implementation of ike_sa_t.set_auth_lifetime.
- */
-static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
+METHOD(ike_sa_t, set_auth_lifetime, void,
+ private_ike_sa_t *this, u_int32_t lifetime)
{
u_int32_t reduction = this->peer_cfg->get_over_time(this->peer_cfg);
u_int32_t reauth_time = time_monotonic(NULL) + lifetime - reduction;
@@ -1823,10 +1718,8 @@ static void set_auth_lifetime(private_ike_sa_t *this, u_int32_t lifetime)
}
}
-/**
- * Implementation of ike_sa_t.roam.
- */
-static status_t roam(private_ike_sa_t *this, bool address)
+METHOD(ike_sa_t, roam, status_t,
+ private_ike_sa_t *this, bool address)
{
host_t *src;
ike_mobike_t *mobike;
@@ -1919,12 +1812,9 @@ static status_t roam(private_ike_sa_t *this, bool address)
return reauth(this);
}
-/**
- * Implementation of ike_sa_t.add_configuration_attribute
- */
-static void add_configuration_attribute(private_ike_sa_t *this,
- attribute_handler_t *handler,
- configuration_attribute_type_t type, chunk_t data)
+METHOD(ike_sa_t, add_configuration_attribute, void,
+ private_ike_sa_t *this, attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data)
{
attribute_entry_t *entry = malloc_thing(attribute_entry_t);
@@ -1935,11 +1825,16 @@ static void add_configuration_attribute(private_ike_sa_t *this,
this->attributes->insert_last(this->attributes, entry);
}
-/**
- * Implementation of ike_sa_t.inherit.
- */
-static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
+METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
+ private_ike_sa_t *this, task_queue_t queue)
+{
+ return this->task_manager->create_task_enumerator(this->task_manager, queue);
+}
+
+METHOD(ike_sa_t, inherit, status_t,
+ private_ike_sa_t *this, ike_sa_t *other_public)
{
+ private_ike_sa_t *other = (private_ike_sa_t*)other_public;
child_sa_t *child_sa;
attribute_entry_t *entry;
@@ -2021,10 +1916,8 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
return this->task_manager->initiate(this->task_manager);
}
-/**
- * Implementation of ike_sa_t.destroy.
- */
-static void destroy(private_ike_sa_t *this)
+METHOD(ike_sa_t, destroy, void,
+ private_ike_sa_t *this)
{
attribute_entry_t *entry;
@@ -2106,122 +1999,107 @@ static void destroy(private_ike_sa_t *this)
*/
ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
{
- private_ike_sa_t *this = malloc_thing(private_ike_sa_t);
+ private_ike_sa_t *this;
static u_int32_t unique_id = 0;
- /* Public functions */
- this->public.get_state = (ike_sa_state_t (*)(ike_sa_t*)) get_state;
- this->public.set_state = (void (*)(ike_sa_t*,ike_sa_state_t)) set_state;
- this->public.get_name = (char* (*)(ike_sa_t*))get_name;
- this->public.get_statistic = (u_int32_t(*)(ike_sa_t*, statistic_t kind))get_statistic;
- this->public.process_message = (status_t (*)(ike_sa_t*, message_t*)) process_message;
- this->public.initiate = (status_t (*)(ike_sa_t*,child_cfg_t*,u_int32_t,traffic_selector_t*,traffic_selector_t*)) initiate;
- this->public.get_ike_cfg = (ike_cfg_t* (*)(ike_sa_t*))get_ike_cfg;
- this->public.set_ike_cfg = (void (*)(ike_sa_t*,ike_cfg_t*))set_ike_cfg;
- this->public.get_peer_cfg = (peer_cfg_t* (*)(ike_sa_t*))get_peer_cfg;
- this->public.set_peer_cfg = (void (*)(ike_sa_t*,peer_cfg_t*))set_peer_cfg;
- this->public.get_auth_cfg = (auth_cfg_t*(*)(ike_sa_t*, bool local))get_auth_cfg;
- this->public.create_auth_cfg_enumerator = (enumerator_t*(*)(ike_sa_t*, bool local))create_auth_cfg_enumerator;
- this->public.add_auth_cfg = (void(*)(ike_sa_t*, bool local, auth_cfg_t *cfg))add_auth_cfg;
- this->public.get_proposal = (proposal_t*(*)(ike_sa_t*))get_proposal;
- this->public.set_proposal = (void(*)(ike_sa_t*, proposal_t *proposal))set_proposal;
- this->public.get_id = (ike_sa_id_t* (*)(ike_sa_t*)) get_id;
- this->public.get_my_host = (host_t* (*)(ike_sa_t*)) get_my_host;
- this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host;
- this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host;
- this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_other_host;
- this->public.set_message_id = (void(*)(ike_sa_t*, bool inbound, u_int32_t mid))set_message_id;
- this->public.update_hosts = (void(*)(ike_sa_t*, host_t *me, host_t *other))update_hosts;
- this->public.get_my_id = (identification_t* (*)(ike_sa_t*)) get_my_id;
- this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id;
- this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id;
- this->public.set_other_id = (void (*)(ike_sa_t*,identification_t*)) set_other_id;
- this->public.get_other_eap_id = (identification_t* (*)(ike_sa_t*)) get_other_eap_id;
- this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
- this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
- this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
- this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
- this->public.set_pending_updates = (void(*)(ike_sa_t*, u_int32_t updates))set_pending_updates;
- this->public.get_pending_updates = (u_int32_t(*)(ike_sa_t*))get_pending_updates;
- this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
- this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
- this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed;
- this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
- this->public.delete = (status_t (*)(ike_sa_t*))delete_;
- this->public.destroy = (void (*)(ike_sa_t*))destroy;
- this->public.send_dpd = (status_t (*)(ike_sa_t*)) send_dpd;
- this->public.send_keepalive = (void (*)(ike_sa_t*)) send_keepalive;
- this->public.get_keymat = (keymat_t*(*)(ike_sa_t*))get_keymat;
- this->public.add_child_sa = (void (*)(ike_sa_t*,child_sa_t*)) add_child_sa;
- this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
- this->public.create_child_sa_iterator = (iterator_t* (*)(ike_sa_t*)) create_child_sa_iterator;
- this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
- this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
- this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
- this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
- this->public.reauth = (status_t (*)(ike_sa_t*))reauth;
- this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
- this->public.set_auth_lifetime = (void(*)(ike_sa_t*, u_int32_t lifetime))set_auth_lifetime;
- this->public.roam = (status_t(*)(ike_sa_t*,bool))roam;
- this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
- this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
- this->public.reset = (void (*)(ike_sa_t*))reset;
- this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id;
- this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
- this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
- this->public.add_configuration_attribute = (void(*)(ike_sa_t*, attribute_handler_t *handler,configuration_attribute_type_t type, chunk_t data))add_configuration_attribute;
- this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
+ INIT(this,
+ .public = {
+ .get_state = _get_state,
+ .set_state = _set_state,
+ .get_name = _get_name,
+ .get_statistic = _get_statistic,
+ .process_message = _process_message,
+ .initiate = _initiate,
+ .get_ike_cfg = _get_ike_cfg,
+ .set_ike_cfg = _set_ike_cfg,
+ .get_peer_cfg = _get_peer_cfg,
+ .set_peer_cfg = _set_peer_cfg,
+ .get_auth_cfg = _get_auth_cfg,
+ .create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
+ .add_auth_cfg = _add_auth_cfg,
+ .get_proposal = _get_proposal,
+ .set_proposal = _set_proposal,
+ .get_id = _get_id,
+ .get_my_host = _get_my_host,
+ .set_my_host = _set_my_host,
+ .get_other_host = _get_other_host,
+ .set_other_host = _set_other_host,
+ .set_message_id = _set_message_id,
+ .update_hosts = _update_hosts,
+ .get_my_id = _get_my_id,
+ .set_my_id = _set_my_id,
+ .get_other_id = _get_other_id,
+ .set_other_id = _set_other_id,
+ .get_other_eap_id = _get_other_eap_id,
+ .enable_extension = _enable_extension,
+ .supports_extension = _supports_extension,
+ .set_condition = _set_condition,
+ .has_condition = _has_condition,
+ .set_pending_updates = _set_pending_updates,
+ .get_pending_updates = _get_pending_updates,
+ .create_additional_address_iterator = _create_additional_address_iterator,
+ .add_additional_address = _add_additional_address,
+ .has_mapping_changed = _has_mapping_changed,
+ .retransmit = _retransmit,
+ .delete = _delete_,
+ .destroy = _destroy,
+ .send_dpd = _send_dpd,
+ .send_keepalive = _send_keepalive,
+ .get_keymat = _get_keymat,
+ .add_child_sa = _add_child_sa,
+ .get_child_sa = _get_child_sa,
+ .create_child_sa_iterator = _create_child_sa_iterator,
+ .rekey_child_sa = _rekey_child_sa,
+ .delete_child_sa = _delete_child_sa,
+ .destroy_child_sa = _destroy_child_sa,
+ .rekey = _rekey,
+ .reauth = _reauth,
+ .reestablish = _reestablish,
+ .set_auth_lifetime = _set_auth_lifetime,
+ .roam = _roam,
+ .inherit = _inherit,
+ .generate_message = _generate_message,
+ .reset = _reset,
+ .get_unique_id = _get_unique_id,
+ .set_virtual_ip = _set_virtual_ip,
+ .get_virtual_ip = _get_virtual_ip,
+ .add_configuration_attribute = _add_configuration_attribute,
+ .set_kmaddress = _set_kmaddress,
+ .create_task_enumerator = _create_task_enumerator,
#ifdef ME
- this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
- this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
- this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
- this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id;
- this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
- this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,chunk_t)) initiate_mediated;
- this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
- this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
- this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
+ .act_as_mediation_server = _act_as_mediation_server,
+ .get_server_reflexive_host = _get_server_reflexive_host,
+ .set_server_reflexive_host = _set_server_reflexive_host,
+ .get_connect_id = _get_connect_id,
+ .initiate_mediation = _initiate_mediation,
+ .initiate_mediated = _initiate_mediated,
+ .relay = _relay,
+ .callback = _callback,
+ .respond = _respond,
#endif /* ME */
-
- /* initialize private fields */
- this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
- this->child_sas = linked_list_create();
- this->my_host = host_create_any(AF_INET);
+ },
+ .ike_sa_id = ike_sa_id->clone(ike_sa_id),
+ .child_sas = linked_list_create(),
+ .my_host = host_create_any(AF_INET),
+ .other_host = host_create_any(AF_INET),
+ .my_id = identification_create_from_encoding(ID_ANY, chunk_empty),
+ .other_id = identification_create_from_encoding(ID_ANY, chunk_empty),
+ .keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id)),
+ .state = IKE_CREATED,
+ .stats[STAT_INBOUND] = time_monotonic(NULL),
+ .stats[STAT_OUTBOUND] = time_monotonic(NULL),
+ .my_auth = auth_cfg_create(),
+ .other_auth = auth_cfg_create(),
+ .my_auths = linked_list_create(),
+ .other_auths = linked_list_create(),
+ .task_manager = task_manager_create(&this->public),
+ .unique_id = ++unique_id,
+ .additional_addresses = linked_list_create(),
+ .attributes = linked_list_create(),
+ .keepalive_interval = lib->settings->get_time(lib->settings,
+ "charon.keep_alive", KEEPALIVE_INTERVAL),
+ );
this->my_host->set_port(this->my_host, IKEV2_UDP_PORT);
- this->other_host = host_create_any(AF_INET);
- this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
- this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
- this->extensions = 0;
- this->conditions = 0;
- this->keymat = keymat_create(ike_sa_id->is_initiator(ike_sa_id));
- this->state = IKE_CREATED;
- this->keepalive_interval = lib->settings->get_time(lib->settings,
- "charon.keep_alive", KEEPALIVE_INTERVAL);
- memset(this->stats, 0, sizeof(this->stats));
- this->stats[STAT_INBOUND] = this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
- this->ike_cfg = NULL;
- this->peer_cfg = NULL;
- this->my_auth = auth_cfg_create();
- this->other_auth = auth_cfg_create();
- this->my_auths = linked_list_create();
- this->other_auths = linked_list_create();
- this->proposal = NULL;
- this->task_manager = task_manager_create(&this->public);
- this->unique_id = ++unique_id;
- this->my_virtual_ip = NULL;
- this->other_virtual_ip = NULL;
- this->additional_addresses = linked_list_create();
- this->attributes = linked_list_create();
- this->nat_detection_dest = chunk_empty;
- this->pending_updates = 0;
- this->keyingtry = 0;
- this->local_host = NULL;
- this->remote_host = NULL;
-#ifdef ME
- this->is_mediation_server = FALSE;
- this->server_reflexive_host = NULL;
- this->connect_id = chunk_empty;
-#endif /* ME */
return &this->public;
}
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index c61502edf..34842a573 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -37,11 +37,11 @@ typedef struct ike_sa_t ike_sa_t;
#include <encoding/payloads/configuration_attribute.h>
#include <sa/ike_sa_id.h>
#include <sa/child_sa.h>
-#include <sa/tasks/task.h>
+#include <sa/task_manager.h>
#include <sa/keymat.h>
#include <config/peer_cfg.h>
#include <config/ike_cfg.h>
-#include <config/auth_cfg.h>
+#include <credentials/auth_cfg.h>
/**
* Timeout in seconds after that a half open IKE_SA gets deleted.
@@ -888,6 +888,14 @@ struct ike_sa_t {
void (*set_kmaddress) (ike_sa_t *this, host_t *local, host_t *remote);
/**
+ * Create enumerator over a task queue of this IKE_SA.
+ *
+ * @param queue type to enumerate
+ * @return enumerator over task_t
+ */
+ enumerator_t* (*create_task_enumerator)(ike_sa_t *this, task_queue_t queue);
+
+ /**
* Inherit all attributes of other to this after rekeying.
*
* When rekeying is completed, all CHILD_SAs, the virtual IP and all
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 3ef0f3bb0..c71c3b297 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -886,9 +886,10 @@ static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id
{
if (wait_for_entry(this, entry, segment))
{
- DBG2(DBG_MGR, "IKE_SA successfully checked out");
entry->checked_out = TRUE;
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -916,7 +917,8 @@ static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
}
ike_sa = ike_sa_create(ike_sa_id);
- DBG2(DBG_MGR, "created IKE_SA");
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
if (!initiator)
{
@@ -971,10 +973,11 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
}
else if (wait_for_entry(this, entry, segment))
{
- DBG2(DBG_MGR, "IKE_SA checked out by hash");
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] checked out by hash",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -998,7 +1001,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
entry->init_hash = hash;
ike_sa = entry->ike_sa;
- DBG2(DBG_MGR, "created IKE_SA");
+ DBG2(DBG_MGR, "created IKE_SA %s[%u]",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
else
{
@@ -1027,7 +1031,6 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
else if (wait_for_entry(this, entry, segment))
{
ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
- DBG2(DBG_MGR, "IKE_SA successfully checked out");
entry->checked_out = TRUE;
entry->message_id = message->get_message_id(message);
if (ike_id->get_responder_spi(ike_id) == 0)
@@ -1035,6 +1038,8 @@ static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
}
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
}
unlock_single_segment(this, segment);
}
@@ -1056,6 +1061,8 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
ike_cfg_t *current_ike;
u_int segment;
+ DBG2(DBG_MGR, "checkout IKE_SA by config");
+
if (!this->reuse_ikesa)
{ /* IKE_SA reuse disable by config */
ike_sa = checkout_new(this, TRUE);
@@ -1081,10 +1088,11 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
current_ike = current_peer->get_ike_cfg(current_peer);
if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg)))
{
- DBG2(DBG_MGR, "found an existing IKE_SA with a '%s' config",
- current_peer->get_name(current_peer));
entry->checked_out = TRUE;
ike_sa = entry->ike_sa;
+ DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config",
+ ike_sa->get_unique_id(ike_sa),
+ current_peer->get_name(current_peer));
break;
}
}
@@ -1112,6 +1120,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
child_sa_t *child_sa;
u_int segment;
+ DBG2(DBG_MGR, "checkout IKE_SA by ID");
+
enumerator = create_table_enumerator(this);
while (enumerator->enumerate(enumerator, &entry, &segment))
{
@@ -1142,6 +1152,8 @@ static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
if (ike_sa)
{
entry->checked_out = TRUE;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
break;
}
}
@@ -1195,6 +1207,8 @@ static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
if (ike_sa)
{
entry->checked_out = TRUE;
+ DBG2(DBG_MGR, "IKE_SA %s[%u] successfully checked out",
+ ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
break;
}
}
@@ -1251,7 +1265,8 @@ static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
other_id = ike_sa->get_other_id(ike_sa);
other = ike_sa->get_other_host(ike_sa);
- DBG2(DBG_MGR, "checkin IKE_SA");
+ DBG2(DBG_MGR, "checkin IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
/* look for the entry */
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
@@ -1327,7 +1342,8 @@ static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa
ike_sa_id = ike_sa->get_id(ike_sa);
- DBG2(DBG_MGR, "checkin and destroy IKE_SA");
+ DBG2(DBG_MGR, "checkin and destroy IKE_SA %s[%u]", ike_sa->get_name(ike_sa),
+ ike_sa->get_unique_id(ike_sa));
if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
{
diff --git a/src/libcharon/sa/task_manager.c b/src/libcharon/sa/task_manager.c
index eeda6c860..a68826440 100644
--- a/src/libcharon/sa/task_manager.c
+++ b/src/libcharon/sa/task_manager.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Tobias Brunner
- * Copyright (C) 2007 Martin Willi
+ * Copyright (C) 2007-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -195,10 +195,8 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
return found;
}
-/**
- * Implementation of task_manager_t.retransmit
- */
-static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
+METHOD(task_manager_t, retransmit, status_t,
+ private_task_manager_t *this, u_int32_t message_id)
{
if (message_id == this->initiating.mid)
{
@@ -281,11 +279,8 @@ static status_t retransmit(private_task_manager_t *this, u_int32_t message_id)
return SUCCESS;
}
-/**
- * build a request using the active task list
- * Implementation of task_manager_t.initiate
- */
-static status_t build_request(private_task_manager_t *this)
+METHOD(task_manager_t, initiate, status_t,
+ private_task_manager_t *this)
{
iterator_t *iterator;
task_t *task;
@@ -296,7 +291,8 @@ static status_t build_request(private_task_manager_t *this)
if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
{
- DBG2(DBG_IKE, "delaying task initiation, exchange in progress");
+ DBG2(DBG_IKE, "delaying task initiation, %N exchange in progress",
+ exchange_type_names, this->initiating.type);
/* do not initiate if we already have a message in the air */
return SUCCESS;
}
@@ -534,7 +530,7 @@ static status_t process_response(private_task_manager_t *this,
{ /* start all over again if we were reset */
this->reset = FALSE;
iterator->destroy(iterator);
- return build_request(this);
+ return initiate(this);
}
}
iterator->destroy(iterator);
@@ -544,7 +540,7 @@ static status_t process_response(private_task_manager_t *this,
this->initiating.packet->destroy(this->initiating.packet);
this->initiating.packet = NULL;
- return build_request(this);
+ return initiate(this);
}
/**
@@ -883,10 +879,8 @@ static status_t process_request(private_task_manager_t *this,
return build_response(this, message);
}
-/**
- * Implementation of task_manager_t.process_message
- */
-static status_t process_message(private_task_manager_t *this, message_t *msg)
+METHOD(task_manager_t, process_message, status_t,
+ private_task_manager_t *this, message_t *msg)
{
u_int32_t mid = msg->get_message_id(msg);
@@ -943,10 +937,8 @@ static status_t process_message(private_task_manager_t *this, message_t *msg)
return SUCCESS;
}
-/**
- * Implementation of task_manager_t.queue_task
- */
-static void queue_task(private_task_manager_t *this, task_t *task)
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
{
if (task->get_type(task) == IKE_MOBIKE)
{ /* there is no need to queue more than one mobike task */
@@ -969,11 +961,10 @@ static void queue_task(private_task_manager_t *this, task_t *task)
this->queued_tasks->insert_last(this->queued_tasks, task);
}
-/**
- * Implementation of task_manager_t.adopt_tasks
- */
-static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *other)
+METHOD(task_manager_t, adopt_tasks, void,
+ private_task_manager_t *this, task_manager_t *other_public)
{
+ private_task_manager_t *other = (private_task_manager_t*)other_public;
task_t *task;
/* move queued tasks from other to this */
@@ -986,20 +977,16 @@ static void adopt_tasks(private_task_manager_t *this, private_task_manager_t *ot
}
}
-/**
- * Implementation of task_manager_t.busy
- */
-static bool busy(private_task_manager_t *this)
+METHOD(task_manager_t, busy, bool,
+ private_task_manager_t *this)
{
return (this->active_tasks->get_count(this->active_tasks) > 0);
}
-/**
- * Implementation of task_manager_t.reset
- */
-static void reset(private_task_manager_t *this,
- u_int32_t initiate, u_int32_t respond)
+METHOD(task_manager_t, reset, void,
+ private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
{
+ enumerator_t *enumerator;
task_t *task;
/* reset message counters and retransmit packets */
@@ -1017,6 +1004,14 @@ static void reset(private_task_manager_t *this,
}
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
+ /* reset queued tasks */
+ enumerator = this->queued_tasks->create_enumerator(this->queued_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ task->migrate(task, this->ike_sa);
+ }
+ enumerator->destroy(enumerator);
+
/* reset active tasks */
while (this->active_tasks->remove_last(this->active_tasks,
(void**)&task) == SUCCESS)
@@ -1028,10 +1023,24 @@ static void reset(private_task_manager_t *this,
this->reset = TRUE;
}
-/**
- * Implementation of task_manager_t.destroy
- */
-static void destroy(private_task_manager_t *this)
+METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
+ private_task_manager_t *this, task_queue_t queue)
+{
+ switch (queue)
+ {
+ case TASK_QUEUE_ACTIVE:
+ return this->active_tasks->create_enumerator(this->active_tasks);
+ case TASK_QUEUE_PASSIVE:
+ return this->passive_tasks->create_enumerator(this->passive_tasks);
+ case TASK_QUEUE_QUEUED:
+ return this->queued_tasks->create_enumerator(this->queued_tasks);
+ default:
+ return enumerator_create_empty();
+ }
+}
+
+METHOD(task_manager_t, destroy, void,
+ private_task_manager_t *this)
{
flush(this);
@@ -1049,34 +1058,32 @@ static void destroy(private_task_manager_t *this)
*/
task_manager_t *task_manager_create(ike_sa_t *ike_sa)
{
- private_task_manager_t *this = malloc_thing(private_task_manager_t);
-
- this->public.process_message = (status_t(*)(task_manager_t*,message_t*))process_message;
- this->public.queue_task = (void(*)(task_manager_t*,task_t*))queue_task;
- this->public.initiate = (status_t(*)(task_manager_t*))build_request;
- this->public.retransmit = (status_t(*)(task_manager_t*,u_int32_t))retransmit;
- this->public.reset = (void(*)(task_manager_t*,u_int32_t,u_int32_t))reset;
- this->public.adopt_tasks = (void(*)(task_manager_t*,task_manager_t*))adopt_tasks;
- this->public.busy = (bool(*)(task_manager_t*))busy;
- this->public.destroy = (void(*)(task_manager_t*))destroy;
-
- this->ike_sa = ike_sa;
- this->responding.packet = NULL;
- this->initiating.packet = NULL;
- this->responding.mid = 0;
- this->initiating.mid = 0;
- this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- this->queued_tasks = linked_list_create();
- this->active_tasks = linked_list_create();
- this->passive_tasks = linked_list_create();
- this->reset = FALSE;
-
- this->retransmit_tries = lib->settings->get_int(lib->settings,
- "charon.retransmit_tries", RETRANSMIT_TRIES);
- this->retransmit_timeout = lib->settings->get_double(lib->settings,
- "charon.retransmit_timeout", RETRANSMIT_TIMEOUT);
- this->retransmit_base = lib->settings->get_double(lib->settings,
- "charon.retransmit_base", RETRANSMIT_BASE);
+ private_task_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .process_message = _process_message,
+ .queue_task = _queue_task,
+ .initiate = _initiate,
+ .retransmit = _retransmit,
+ .reset = _reset,
+ .adopt_tasks = _adopt_tasks,
+ .busy = _busy,
+ .create_task_enumerator = _create_task_enumerator,
+ .destroy = _destroy,
+ },
+ .ike_sa = ike_sa,
+ .initiating.type = EXCHANGE_TYPE_UNDEFINED,
+ .queued_tasks = linked_list_create(),
+ .active_tasks = linked_list_create(),
+ .passive_tasks = linked_list_create(),
+ .retransmit_tries = lib->settings->get_int(lib->settings,
+ "charon.retransmit_tries", RETRANSMIT_TRIES),
+ .retransmit_timeout = lib->settings->get_double(lib->settings,
+ "charon.retransmit_timeout", RETRANSMIT_TIMEOUT),
+ .retransmit_base = lib->settings->get_double(lib->settings,
+ "charon.retransmit_base", RETRANSMIT_BASE),
+ );
return &this->public;
}
diff --git a/src/libcharon/sa/task_manager.h b/src/libcharon/sa/task_manager.h
index 731ed4898..14fccd5f9 100644
--- a/src/libcharon/sa/task_manager.h
+++ b/src/libcharon/sa/task_manager.h
@@ -22,6 +22,7 @@
#define TASK_MANAGER_H_
typedef struct task_manager_t task_manager_t;
+typedef enum task_queue_t task_queue_t;
#include <limits.h>
@@ -55,6 +56,17 @@ typedef struct task_manager_t task_manager_t;
*/
#define ROUTEABILITY_CHECK_TRIES 10
+/**
+ * Type of task queues the task manager uses to handle tasks
+ */
+enum task_queue_t {
+ /** tasks currently active, initiated by us */
+ TASK_QUEUE_ACTIVE,
+ /** passive tasks initiated by the remote peer */
+ TASK_QUEUE_PASSIVE,
+ /** tasks queued for initiated, but not yet activated */
+ TASK_QUEUE_QUEUED,
+};
/**
* The task manager, juggles task and handles message exchanges.
@@ -158,6 +170,15 @@ struct task_manager_t {
bool (*busy) (task_manager_t *this);
/**
+ * Create an enumerator over tasks in a specific queue.
+ *
+ * @param queue queue to create an enumerator over
+ * @return enumerator over task_t
+ */
+ enumerator_t* (*create_task_enumerator)(task_manager_t *this,
+ task_queue_t queue);
+
+ /**
* Destroy the task_manager_t.
*/
void (*destroy) (task_manager_t *this);
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
index bea4f73d5..3de27ee3f 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
* - INVALID_ARG: diffie hellman group inacceptable
* - NOT_FOUND: TS inacceptable
*/
-static status_t select_and_install(private_child_create_t *this, bool no_dh)
+static status_t select_and_install(private_child_create_t *this,
+ bool no_dh, bool ike_auth)
{
status_t status, status_i, status_o;
chunk_t nonce_i, nonce_r;
@@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
other_vip);
+ if (this->initiator)
+ {
+ if (ike_auth)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
+ }
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER, my_ts, other_ts);
+ }
+
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
{
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
@@ -418,66 +438,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
- /* check for any certificate-based IP address block constraints */
- if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL)
- {
- auth_cfg_t *auth;
- enumerator_t *auth_enum;
- certificate_t *cert = NULL;
-
- auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
- while (auth_enum->enumerate(auth_enum, &auth))
- {
- cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
- if (cert)
- {
- break;
- }
- }
- auth_enum->destroy(auth_enum);
-
- if (cert && cert->get_type(cert) == CERT_X509)
- {
- x509_t *x509 = (x509_t*)cert;
-
- if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
- {
- enumerator_t *enumerator, *block_enum;
- traffic_selector_t *ts, *block_ts;
-
- DBG1(DBG_IKE, "checking certificate-based traffic selector "
- "constraints [RFC 3779]");
- enumerator = other_ts->create_enumerator(other_ts);
- while (enumerator->enumerate(enumerator, &ts))
- {
- bool contained = FALSE;
-
- block_enum = x509->create_ipAddrBlock_enumerator(x509);
- while (block_enum->enumerate(block_enum, &block_ts))
- {
- if (ts->is_contained_in(ts, block_ts))
- {
- DBG1(DBG_IKE, " TS %R is contained in address block"
- " constraint %R", ts, block_ts);
- contained = TRUE;
- break;
- }
- }
- block_enum->destroy(block_enum);
-
- if (!contained)
- {
- DBG1(DBG_IKE, " TS %R is not contained in any"
- " address block constraint", ts);
- enumerator->destroy(enumerator);
- return FAILED;
- }
- }
- enumerator->destroy(enumerator);
- }
- }
- }
-
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
this->child_sa->set_mode(this->child_sa, this->mode);
@@ -529,8 +489,8 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
return NOT_FOUND;
}
- charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
- nonce_i, nonce_r);
+ charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
+ this->dh, nonce_i, nonce_r);
/* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
@@ -848,6 +808,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
}
+ if (message->get_exchange_type(message) == IKE_AUTH)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
+ }
+
build_payloads(this, message);
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
@@ -914,7 +885,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
peer_cfg_t *peer_cfg;
payload_t *payload;
enumerator_t *enumerator;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -934,6 +905,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1016,7 +988,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
}
- switch (select_and_install(this, no_dh))
+ switch (select_and_install(this, no_dh, ike_auth))
{
case SUCCESS:
break;
@@ -1064,7 +1036,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -1079,6 +1051,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1159,7 +1132,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
return SUCCESS;
}
- if (select_and_install(this, no_dh) == SUCCESS)
+ if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
{
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
@@ -1229,11 +1202,11 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
- if (this->tsi)
+ if (this->tsr)
{
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
}
- if (this->tsr)
+ if (this->tsi)
{
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
}
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c
index d7c6b0541..b0cd30e1e 100644
--- a/src/libcharon/sa/tasks/child_delete.c
+++ b/src/libcharon/sa/tasks/child_delete.c
@@ -191,6 +191,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
child_cfg_t *child_cfg;
protocol_id_t protocol;
u_int32_t spi;
+ action_t action;
status_t status = SUCCESS;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -205,10 +206,11 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
protocol = child_sa->get_protocol(child_sa);
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
+ action = child_sa->get_close_action(child_sa);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
if (this->check_delete_action)
{ /* enforce child_cfg policy if deleted passively */
- switch (child_cfg->get_close_action(child_cfg))
+ switch (action)
{
case ACTION_RESTART:
child_cfg->get_ref(child_cfg);
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
index b5e4e84b4..fb3452efd 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -215,6 +215,64 @@ static status_t build_r(private_child_rekey_t *this, message_t *message)
}
/**
+ * Handle a rekey collision
+ */
+static child_sa_t *handle_collision(private_child_rekey_t *this)
+{
+ child_sa_t *to_delete;
+
+ if (this->collision->get_type(this->collision) == CHILD_REKEY)
+ {
+ chunk_t this_nonce, other_nonce;
+ private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
+
+ this_nonce = this->child_create->get_lower_nonce(this->child_create);
+ other_nonce = other->child_create->get_lower_nonce(other->child_create);
+
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ child_sa_t *child_sa;
+
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ /* disable close action for the redundand child */
+ child_sa = other->child_create->get_child(other->child_create);
+ child_sa->set_close_action(child_sa, ACTION_NONE);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey collision lost, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ else
+ { /* CHILD_DELETE */
+ child_delete_t *del = (child_delete_t*)this->collision;
+
+ /* we didn't had a chance to compare the nonces, so we delete
+ * the CHILD_SA the other is not deleting. */
+ if (del->get_child(del) != this->child_sa)
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ return to_delete;
+}
+
+/**
* Implementation of task_t.process for initiator
*/
static status_t process_i(private_child_rekey_t *this, message_t *message)
@@ -263,35 +321,14 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
return SUCCESS;
}
- to_delete = this->child_sa;
-
/* check for rekey collisions */
- if (this->collision &&
- this->collision->get_type(this->collision) == CHILD_REKEY)
+ if (this->collision)
{
- chunk_t this_nonce, other_nonce;
- private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
-
- this_nonce = this->child_create->get_lower_nonce(this->child_create);
- other_nonce = other->child_create->get_lower_nonce(other->child_create);
-
- /* if we have the lower nonce, delete rekeyed SA. If not, delete
- * the redundant. */
- if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) < 0)
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child");
- }
- else
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child");
- to_delete = this->child_create->get_child(this->child_create);
- if (to_delete == NULL)
- {
- /* ooops, should not happen, fallback */
- to_delete = this->child_sa;
- }
- }
+ to_delete = handle_collision(this);
+ }
+ else
+ {
+ to_delete = this->child_sa;
}
if (to_delete != this->child_create->get_child(this->child_create))
@@ -300,6 +337,10 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
this->child_create->get_child(this->child_create));
}
+ if (to_delete == NULL)
+ {
+ return SUCCESS;
+ }
spi = to_delete->get_spi(to_delete, TRUE);
protocol = to_delete->get_protocol(to_delete);
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
index a07f96767..a954782f2 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -518,6 +518,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
{ /* peer requested EAP, but current config does not match */
+ DBG1(DBG_IKE, "peer requested EAP, config inacceptable");
this->peer_cfg->destroy(this->peer_cfg);
this->peer_cfg = NULL;
if (!update_cfg_candidates(this, FALSE))
@@ -527,7 +528,16 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
}
cand = get_auth_cfg(this, FALSE);
}
- cfg->merge(cfg, cand, TRUE);
+ /* copy over the EAP specific rules for authentication */
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE,
+ cand->get(cand, AUTH_RULE_EAP_TYPE));
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR,
+ cand->get(cand, AUTH_RULE_EAP_VENDOR));
+ id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ }
}
/* verify authentication data */
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c
index c831df975..cc810a49a 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/tasks/ike_cert_post.c
@@ -72,14 +72,18 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
return cert_payload_create_from_cert(cert);
}
- encoded = cert->get_encoding(cert);
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
+ {
+ DBG1(DBG_IKE, "encoding certificate for cert payload failed");
+ hasher->destroy(hasher);
+ return NULL;
+ }
hasher->allocate_hash(hasher, encoded, &hash);
chunk_free(&encoded);
hasher->destroy(hasher);
id = identification_create_from_encoding(ID_KEY_ID, hash);
- enumerator = charon->credentials->create_cdp_enumerator(charon->credentials,
- CERT_X509, id);
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509, id);
if (enumerator->enumerate(enumerator, &url))
{
payload = cert_payload_create_from_hash_and_url(hash, url);
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
index 0805d0290..1c0c54727 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -93,8 +93,8 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
certificate_t *cert;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, TRUE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, TRUE);
if (cert)
{
DBG1(DBG_IKE, "received cert request for \"%Y\"",
@@ -156,8 +156,8 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload)
break;
}
id = identification_create_from_encoding(ID_KEY_ID, hash);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, FALSE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, FALSE);
id->destroy(id);
break;
}
@@ -299,7 +299,7 @@ static void add_certreq(certreq_payload_t **req, certificate_t *cert)
{
*req = certreq_payload_create_type(CERT_X509);
}
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
{
(*req)->add_keyid(*req, keyid);
DBG1(DBG_IKE, "sending cert request for \"%Y\"",
@@ -370,8 +370,8 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
if (!req)
{
/* otherwise add all trusted CA certificates */
- enumerator = charon->credentials->create_cert_enumerator(
- charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_ANY, KEY_ANY, NULL, TRUE);
while (enumerator->enumerate(enumerator, &cert))
{
add_certreq(&req, cert);
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c
index 58bcf0762..c92b5bca5 100644
--- a/src/libcharon/sa/tasks/ike_config.c
+++ b/src/libcharon/sa/tasks/ike_config.c
@@ -333,7 +333,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
chunk_empty);
return SUCCESS;
}
- DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp = cp_payload_create_type(CFG_REPLY);
@@ -342,7 +342,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, id, vip);
+ hydra->attributes, config->get_pool(config), id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c
index 5eb33b540..38fb572f4 100644
--- a/src/libcharon/sa/tasks/ike_init.c
+++ b/src/libcharon/sa/tasks/ike_init.c
@@ -543,6 +543,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
DESTROY_IF(this->dh);
this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 878170c83..80bf647cd 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -128,7 +128,7 @@ static u_int32_t install(private_trap_manager_t *this, peer_cfg_t *peer,
ike_cfg = peer->get_ike_cfg(peer);
other = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg),
0, ike_cfg->get_other_port(ike_cfg));
- if (!other)
+ if (!other || other->is_anyaddr(other))
{
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
return 0;