summaryrefslogtreecommitdiff
path: root/src/libcharon
diff options
context:
space:
mode:
authorRomain Francoise <rfrancoise@debian.org>2014-10-21 19:28:38 +0200
committerRomain Francoise <rfrancoise@debian.org>2014-10-21 19:41:50 +0200
commitb23b0e5609ed4b3d29396a1727aab035fa4a395f (patch)
tree091d0b144dd92a0c124b7fbe9eae68f79cb975dc /src/libcharon
parent4a01a7e2574040cf246fd00ebff173b873c17349 (diff)
downloadvyos-strongswan-b23b0e5609ed4b3d29396a1727aab035fa4a395f.tar.gz
vyos-strongswan-b23b0e5609ed4b3d29396a1727aab035fa4a395f.zip
Import upstream release 5.2.1
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Android.mk3
-rw-r--r--src/libcharon/Makefile.am10
-rw-r--r--src/libcharon/Makefile.in296
-rw-r--r--src/libcharon/bus/bus.c37
-rw-r--r--src/libcharon/bus/bus.h23
-rw-r--r--src/libcharon/bus/listeners/listener.h18
-rw-r--r--src/libcharon/config/child_cfg.c11
-rw-r--r--src/libcharon/config/proposal.c10
-rw-r--r--src/libcharon/daemon.c2
-rw-r--r--src/libcharon/encoding/message.c997
-rw-r--r--src/libcharon/encoding/message.h72
-rw-r--r--src/libcharon/encoding/parser.c2
-rw-r--r--src/libcharon/encoding/payloads/encrypted_fragment_payload.h85
-rw-r--r--src/libcharon/encoding/payloads/encrypted_payload.c1022
-rw-r--r--src/libcharon/encoding/payloads/encrypted_payload.h (renamed from src/libcharon/encoding/payloads/encryption_payload.h)57
-rw-r--r--src/libcharon/encoding/payloads/encryption_payload.c634
-rw-r--r--src/libcharon/encoding/payloads/ike_header.c16
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.c18
-rw-r--r--src/libcharon/encoding/payloads/notify_payload.h4
-rw-r--r--src/libcharon/encoding/payloads/payload.c41
-rw-r--r--src/libcharon/encoding/payloads/payload.h24
-rw-r--r--src/libcharon/encoding/payloads/sa_payload.c17
-rw-r--r--src/libcharon/network/receiver.c4
-rw-r--r--src/libcharon/plugins/addrblock/Makefile.in8
-rw-r--r--src/libcharon/plugins/android_dns/Makefile.in8
-rw-r--r--src/libcharon/plugins/android_log/Makefile.in8
-rw-r--r--src/libcharon/plugins/certexpire/Makefile.in8
-rw-r--r--src/libcharon/plugins/coupling/Makefile.in8
-rw-r--r--src/libcharon/plugins/dhcp/Makefile.in8
-rw-r--r--src/libcharon/plugins/dnscert/Makefile.in8
-rw-r--r--src/libcharon/plugins/duplicheck/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_aka/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_aka_3gpp2/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_dynamic/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_gtc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_identity/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_md5/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_mschapv2/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_peap/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_radius/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c50
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c10
-rw-r--r--src/libcharon/plugins/eap_sim/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_sim_file/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_sim_pcsc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_reauth/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_simaka_sql/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_tls/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_tnc/Makefile.in8
-rw-r--r--src/libcharon/plugins/eap_ttls/Makefile.in8
-rw-r--r--src/libcharon/plugins/error_notify/Makefile.in8
-rw-r--r--src/libcharon/plugins/ext_auth/Makefile.am18
-rw-r--r--src/libcharon/plugins/ext_auth/Makefile.in774
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_listener.c203
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_listener.h59
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_plugin.c156
-rw-r--r--src/libcharon/plugins/ext_auth/ext_auth_plugin.h49
-rw-r--r--src/libcharon/plugins/farp/Makefile.in8
-rw-r--r--src/libcharon/plugins/ha/Makefile.in8
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c2
-rw-r--r--src/libcharon/plugins/ipseckey/Makefile.in8
-rw-r--r--src/libcharon/plugins/kernel_iph/Makefile.in8
-rw-r--r--src/libcharon/plugins/kernel_libipsec/Makefile.in8
-rw-r--r--src/libcharon/plugins/kernel_wfp/Makefile.in8
-rw-r--r--src/libcharon/plugins/led/Makefile.in8
-rw-r--r--src/libcharon/plugins/load_tester/Makefile.in8
-rw-r--r--src/libcharon/plugins/lookip/Makefile.in8
-rw-r--r--src/libcharon/plugins/maemo/Makefile.in8
-rw-r--r--src/libcharon/plugins/medcli/Makefile.in8
-rw-r--r--src/libcharon/plugins/medsrv/Makefile.in8
-rw-r--r--src/libcharon/plugins/osx_attr/Makefile.in8
-rw-r--r--src/libcharon/plugins/radattr/Makefile.in8
-rw-r--r--src/libcharon/plugins/smp/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_default/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c5
-rw-r--r--src/libcharon/plugins/socket_dynamic/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c5
-rw-r--r--src/libcharon/plugins/socket_win/Makefile.in8
-rw-r--r--src/libcharon/plugins/socket_win/socket_win_socket.c5
-rw-r--r--src/libcharon/plugins/sql/Makefile.in8
-rw-r--r--src/libcharon/plugins/stroke/Makefile.in8
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c12
-rw-r--r--src/libcharon/plugins/systime_fix/Makefile.in8
-rw-r--r--src/libcharon/plugins/tnc_ifmap/Makefile.in8
-rw-r--r--src/libcharon/plugins/tnc_pdp/Makefile.in8
-rw-r--r--src/libcharon/plugins/uci/Makefile.in8
-rw-r--r--src/libcharon/plugins/unit_tester/Makefile.in8
-rw-r--r--src/libcharon/plugins/unity/Makefile.in8
-rw-r--r--src/libcharon/plugins/unity/unity_narrow.c69
-rw-r--r--src/libcharon/plugins/updown/Makefile.in8
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c461
-rw-r--r--src/libcharon/plugins/vici/Makefile.am7
-rw-r--r--src/libcharon/plugins/vici/Makefile.in210
-rw-r--r--src/libcharon/plugins/vici/README.md698
-rw-r--r--src/libcharon/plugins/vici/libvici.c5
-rw-r--r--src/libcharon/plugins/vici/libvici.h4
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.am22
-rw-r--r--src/libcharon/plugins/vici/ruby/Makefile.in556
-rw-r--r--src/libcharon/plugins/vici/ruby/lib/vici.rb569
-rw-r--r--src/libcharon/plugins/vici/ruby/vici.gemspec.in16
-rw-r--r--src/libcharon/plugins/vici/suites/test_message.c2
-rw-r--r--src/libcharon/plugins/vici/vici_control.c12
-rw-r--r--src/libcharon/plugins/vici/vici_cred.c5
-rw-r--r--src/libcharon/plugins/vici/vici_message.c4
-rw-r--r--src/libcharon/plugins/whitelist/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_eap/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_generic/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_noauth/Makefile.in8
-rw-r--r--src/libcharon/plugins/xauth_pam/Makefile.in8
-rw-r--r--src/libcharon/processing/jobs/adopt_children_job.c40
-rw-r--r--src/libcharon/processing/jobs/adopt_children_job.h8
-rw-r--r--src/libcharon/processing/jobs/update_sa_job.c7
-rw-r--r--src/libcharon/sa/ike_sa.c138
-rw-r--r--src/libcharon/sa/ike_sa.h34
-rw-r--r--src/libcharon/sa/ike_sa_manager.c48
-rw-r--r--src/libcharon/sa/ikev1/phase1.c12
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c445
-rw-r--r--src/libcharon/sa/ikev1/tasks/aggressive_mode.c32
-rw-r--r--src/libcharon/sa/ikev1/tasks/informational.c6
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.c39
-rw-r--r--src/libcharon/sa/ikev1/tasks/main_mode.c31
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c26
-rw-r--r--src/libcharon/sa/ikev1/tasks/xauth.c23
-rw-r--r--src/libcharon/sa/ikev1/tasks/xauth.h5
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c307
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c23
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.c95
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_mobike.h8
129 files changed, 7369 insertions, 1821 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index a28b459de..4212ee87a 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -25,7 +25,8 @@ encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
encoding/payloads/encodings.c encoding/payloads/encodings.h \
-encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
+encoding/payloads/encrypted_payload.c encoding/payloads/encrypted_payload.h \
+encoding/payloads/encrypted_fragment_payload.h \
encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index e81c42405..e98f5e137 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -23,7 +23,8 @@ encoding/payloads/cp_payload.c encoding/payloads/cp_payload.h \
encoding/payloads/delete_payload.c encoding/payloads/delete_payload.h \
encoding/payloads/eap_payload.c encoding/payloads/eap_payload.h \
encoding/payloads/encodings.c encoding/payloads/encodings.h \
-encoding/payloads/encryption_payload.c encoding/payloads/encryption_payload.h \
+encoding/payloads/encrypted_payload.c encoding/payloads/encrypted_payload.h \
+encoding/payloads/encrypted_fragment_payload.h \
encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
@@ -258,6 +259,13 @@ if MONOLITHIC
endif
endif
+if USE_EXT_AUTH
+ SUBDIRS += plugins/ext_auth
+if MONOLITHIC
+ libcharon_la_LIBADD += plugins/ext_auth/libstrongswan-ext-auth.la
+endif
+endif
+
if USE_EAP_IDENTITY
SUBDIRS += plugins/eap_identity
if MONOLITHIC
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index 002da511d..4d89794b5 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -162,106 +162,108 @@ host_triplet = @host@
@MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE@am__append_27 = plugins/ipseckey/libstrongswan-ipseckey.la
@USE_UPDOWN_TRUE@am__append_28 = plugins/updown
@MONOLITHIC_TRUE@@USE_UPDOWN_TRUE@am__append_29 = plugins/updown/libstrongswan-updown.la
-@USE_EAP_IDENTITY_TRUE@am__append_30 = plugins/eap_identity
-@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_31 = plugins/eap_identity/libstrongswan-eap-identity.la
-@USE_EAP_SIM_TRUE@am__append_32 = plugins/eap_sim
-@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_33 = plugins/eap_sim/libstrongswan-eap-sim.la
-@USE_EAP_SIM_FILE_TRUE@am__append_34 = plugins/eap_sim_file
-@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_35 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
-@USE_EAP_SIM_PCSC_TRUE@am__append_36 = plugins/eap_sim_pcsc
-@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_37 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
-@USE_EAP_SIMAKA_SQL_TRUE@am__append_38 = plugins/eap_simaka_sql
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_39 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
-@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_40 = plugins/eap_simaka_pseudonym
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_41 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
-@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_42 = plugins/eap_simaka_reauth
-@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_43 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
-@USE_EAP_AKA_TRUE@am__append_44 = plugins/eap_aka
-@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_45 = plugins/eap_aka/libstrongswan-eap-aka.la
-@USE_EAP_AKA_3GPP2_TRUE@am__append_46 = plugins/eap_aka_3gpp2
-@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_47 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
-@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_48 = $(top_builddir)/src/libsimaka/libsimaka.la
-@USE_EAP_MD5_TRUE@am__append_49 = plugins/eap_md5
-@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_50 = plugins/eap_md5/libstrongswan-eap-md5.la
-@USE_EAP_GTC_TRUE@am__append_51 = plugins/eap_gtc
-@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_52 = plugins/eap_gtc/libstrongswan-eap-gtc.la
-@USE_EAP_MSCHAPV2_TRUE@am__append_53 = plugins/eap_mschapv2
-@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_54 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
-@USE_EAP_DYNAMIC_TRUE@am__append_55 = plugins/eap_dynamic
-@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_56 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
-@USE_EAP_RADIUS_TRUE@am__append_57 = plugins/eap_radius
-@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_58 = plugins/eap_radius/libstrongswan-eap-radius.la
-@USE_EAP_TLS_TRUE@am__append_59 = plugins/eap_tls
-@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_60 = plugins/eap_tls/libstrongswan-eap-tls.la
-@USE_EAP_TTLS_TRUE@am__append_61 = plugins/eap_ttls
-@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_62 = plugins/eap_ttls/libstrongswan-eap-ttls.la
-@USE_EAP_PEAP_TRUE@am__append_63 = plugins/eap_peap
-@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_64 = plugins/eap_peap/libstrongswan-eap-peap.la
-@USE_EAP_TNC_TRUE@am__append_65 = plugins/eap_tnc
-@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_66 = plugins/eap_tnc/libstrongswan-eap-tnc.la
-@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_67 = $(top_builddir)/src/libtls/libtls.la
-@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_68 = $(top_builddir)/src/libradius/libradius.la
-@USE_TNC_IFMAP_TRUE@am__append_69 = plugins/tnc_ifmap
-@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_70 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
-@USE_TNC_PDP_TRUE@am__append_71 = plugins/tnc_pdp
-@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_72 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
-@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_73 = $(top_builddir)/src/libtnccs/libtnccs.la
-@USE_MEDSRV_TRUE@am__append_74 = plugins/medsrv
-@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_75 = plugins/medsrv/libstrongswan-medsrv.la
-@USE_MEDCLI_TRUE@am__append_76 = plugins/medcli
-@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_77 = plugins/medcli/libstrongswan-medcli.la
-@USE_DHCP_TRUE@am__append_78 = plugins/dhcp
-@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_79 = plugins/dhcp/libstrongswan-dhcp.la
-@USE_OSX_ATTR_TRUE@am__append_80 = plugins/osx_attr
-@MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_81 = plugins/osx_attr/libstrongswan-osx-attr.la
-@USE_ANDROID_DNS_TRUE@am__append_82 = plugins/android_dns
-@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_83 = plugins/android_dns/libstrongswan-android-dns.la
-@USE_ANDROID_LOG_TRUE@am__append_84 = plugins/android_log
-@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_85 = plugins/android_log/libstrongswan-android-log.la
-@USE_MAEMO_TRUE@am__append_86 = plugins/maemo
-@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_87 = plugins/maemo/libstrongswan-maemo.la
-@USE_HA_TRUE@am__append_88 = plugins/ha
-@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_89 = plugins/ha/libstrongswan-ha.la
-@USE_KERNEL_LIBIPSEC_TRUE@am__append_90 = plugins/kernel_libipsec
-@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_91 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
-@USE_KERNEL_WFP_TRUE@am__append_92 = plugins/kernel_wfp
-@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_93 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
-@USE_KERNEL_IPH_TRUE@am__append_94 = plugins/kernel_iph
-@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_95 = plugins/kernel_iph/libstrongswan-kernel-iph.la
-@USE_WHITELIST_TRUE@am__append_96 = plugins/whitelist
-@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_97 = plugins/whitelist/libstrongswan-whitelist.la
-@USE_LOOKIP_TRUE@am__append_98 = plugins/lookip
-@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_99 = plugins/lookip/libstrongswan-lookip.la
-@USE_ERROR_NOTIFY_TRUE@am__append_100 = plugins/error_notify
-@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_101 = plugins/error_notify/libstrongswan-error-notify.la
-@USE_CERTEXPIRE_TRUE@am__append_102 = plugins/certexpire
-@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_103 = plugins/certexpire/libstrongswan-certexpire.la
-@USE_SYSTIME_FIX_TRUE@am__append_104 = plugins/systime_fix
-@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_105 = plugins/systime_fix/libstrongswan-systime-fix.la
-@USE_LED_TRUE@am__append_106 = plugins/led
-@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_107 = plugins/led/libstrongswan-led.la
-@USE_DUPLICHECK_TRUE@am__append_108 = plugins/duplicheck
-@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_109 = plugins/duplicheck/libstrongswan-duplicheck.la
-@USE_COUPLING_TRUE@am__append_110 = plugins/coupling
-@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_111 = plugins/coupling/libstrongswan-coupling.la
-@USE_RADATTR_TRUE@am__append_112 = plugins/radattr
-@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_113 = plugins/radattr/libstrongswan-radattr.la
-@USE_UCI_TRUE@am__append_114 = plugins/uci
-@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_115 = plugins/uci/libstrongswan-uci.la
-@USE_ADDRBLOCK_TRUE@am__append_116 = plugins/addrblock
-@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_117 = plugins/addrblock/libstrongswan-addrblock.la
-@USE_UNITY_TRUE@am__append_118 = plugins/unity
-@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_119 = plugins/unity/libstrongswan-unity.la
-@USE_UNIT_TESTS_TRUE@am__append_120 = plugins/unit_tester
-@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_121 = plugins/unit_tester/libstrongswan-unit-tester.la
-@USE_XAUTH_GENERIC_TRUE@am__append_122 = plugins/xauth_generic
-@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_123 = plugins/xauth_generic/libstrongswan-xauth-generic.la
-@USE_XAUTH_EAP_TRUE@am__append_124 = plugins/xauth_eap
-@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_125 = plugins/xauth_eap/libstrongswan-xauth-eap.la
-@USE_XAUTH_PAM_TRUE@am__append_126 = plugins/xauth_pam
-@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_127 = plugins/xauth_pam/libstrongswan-xauth-pam.la
-@USE_XAUTH_NOAUTH_TRUE@am__append_128 = plugins/xauth_noauth
-@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_129 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
+@USE_EXT_AUTH_TRUE@am__append_30 = plugins/ext_auth
+@MONOLITHIC_TRUE@@USE_EXT_AUTH_TRUE@am__append_31 = plugins/ext_auth/libstrongswan-ext-auth.la
+@USE_EAP_IDENTITY_TRUE@am__append_32 = plugins/eap_identity
+@MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE@am__append_33 = plugins/eap_identity/libstrongswan-eap-identity.la
+@USE_EAP_SIM_TRUE@am__append_34 = plugins/eap_sim
+@MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE@am__append_35 = plugins/eap_sim/libstrongswan-eap-sim.la
+@USE_EAP_SIM_FILE_TRUE@am__append_36 = plugins/eap_sim_file
+@MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE@am__append_37 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+@USE_EAP_SIM_PCSC_TRUE@am__append_38 = plugins/eap_sim_pcsc
+@MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE@am__append_39 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
+@USE_EAP_SIMAKA_SQL_TRUE@am__append_40 = plugins/eap_simaka_sql
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE@am__append_41 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_42 = plugins/eap_simaka_pseudonym
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_43 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_44 = plugins/eap_simaka_reauth
+@MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE@am__append_45 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+@USE_EAP_AKA_TRUE@am__append_46 = plugins/eap_aka
+@MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE@am__append_47 = plugins/eap_aka/libstrongswan-eap-aka.la
+@USE_EAP_AKA_3GPP2_TRUE@am__append_48 = plugins/eap_aka_3gpp2
+@MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE@am__append_49 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+@MONOLITHIC_TRUE@@USE_SIMAKA_TRUE@am__append_50 = $(top_builddir)/src/libsimaka/libsimaka.la
+@USE_EAP_MD5_TRUE@am__append_51 = plugins/eap_md5
+@MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE@am__append_52 = plugins/eap_md5/libstrongswan-eap-md5.la
+@USE_EAP_GTC_TRUE@am__append_53 = plugins/eap_gtc
+@MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE@am__append_54 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+@USE_EAP_MSCHAPV2_TRUE@am__append_55 = plugins/eap_mschapv2
+@MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE@am__append_56 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+@USE_EAP_DYNAMIC_TRUE@am__append_57 = plugins/eap_dynamic
+@MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE@am__append_58 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
+@USE_EAP_RADIUS_TRUE@am__append_59 = plugins/eap_radius
+@MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE@am__append_60 = plugins/eap_radius/libstrongswan-eap-radius.la
+@USE_EAP_TLS_TRUE@am__append_61 = plugins/eap_tls
+@MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE@am__append_62 = plugins/eap_tls/libstrongswan-eap-tls.la
+@USE_EAP_TTLS_TRUE@am__append_63 = plugins/eap_ttls
+@MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE@am__append_64 = plugins/eap_ttls/libstrongswan-eap-ttls.la
+@USE_EAP_PEAP_TRUE@am__append_65 = plugins/eap_peap
+@MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE@am__append_66 = plugins/eap_peap/libstrongswan-eap-peap.la
+@USE_EAP_TNC_TRUE@am__append_67 = plugins/eap_tnc
+@MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE@am__append_68 = plugins/eap_tnc/libstrongswan-eap-tnc.la
+@MONOLITHIC_TRUE@@USE_TLS_TRUE@am__append_69 = $(top_builddir)/src/libtls/libtls.la
+@MONOLITHIC_TRUE@@USE_RADIUS_TRUE@am__append_70 = $(top_builddir)/src/libradius/libradius.la
+@USE_TNC_IFMAP_TRUE@am__append_71 = plugins/tnc_ifmap
+@MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE@am__append_72 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
+@USE_TNC_PDP_TRUE@am__append_73 = plugins/tnc_pdp
+@MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE@am__append_74 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
+@MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE@am__append_75 = $(top_builddir)/src/libtnccs/libtnccs.la
+@USE_MEDSRV_TRUE@am__append_76 = plugins/medsrv
+@MONOLITHIC_TRUE@@USE_MEDSRV_TRUE@am__append_77 = plugins/medsrv/libstrongswan-medsrv.la
+@USE_MEDCLI_TRUE@am__append_78 = plugins/medcli
+@MONOLITHIC_TRUE@@USE_MEDCLI_TRUE@am__append_79 = plugins/medcli/libstrongswan-medcli.la
+@USE_DHCP_TRUE@am__append_80 = plugins/dhcp
+@MONOLITHIC_TRUE@@USE_DHCP_TRUE@am__append_81 = plugins/dhcp/libstrongswan-dhcp.la
+@USE_OSX_ATTR_TRUE@am__append_82 = plugins/osx_attr
+@MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE@am__append_83 = plugins/osx_attr/libstrongswan-osx-attr.la
+@USE_ANDROID_DNS_TRUE@am__append_84 = plugins/android_dns
+@MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE@am__append_85 = plugins/android_dns/libstrongswan-android-dns.la
+@USE_ANDROID_LOG_TRUE@am__append_86 = plugins/android_log
+@MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE@am__append_87 = plugins/android_log/libstrongswan-android-log.la
+@USE_MAEMO_TRUE@am__append_88 = plugins/maemo
+@MONOLITHIC_TRUE@@USE_MAEMO_TRUE@am__append_89 = plugins/maemo/libstrongswan-maemo.la
+@USE_HA_TRUE@am__append_90 = plugins/ha
+@MONOLITHIC_TRUE@@USE_HA_TRUE@am__append_91 = plugins/ha/libstrongswan-ha.la
+@USE_KERNEL_LIBIPSEC_TRUE@am__append_92 = plugins/kernel_libipsec
+@MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE@am__append_93 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
+@USE_KERNEL_WFP_TRUE@am__append_94 = plugins/kernel_wfp
+@MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE@am__append_95 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
+@USE_KERNEL_IPH_TRUE@am__append_96 = plugins/kernel_iph
+@MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE@am__append_97 = plugins/kernel_iph/libstrongswan-kernel-iph.la
+@USE_WHITELIST_TRUE@am__append_98 = plugins/whitelist
+@MONOLITHIC_TRUE@@USE_WHITELIST_TRUE@am__append_99 = plugins/whitelist/libstrongswan-whitelist.la
+@USE_LOOKIP_TRUE@am__append_100 = plugins/lookip
+@MONOLITHIC_TRUE@@USE_LOOKIP_TRUE@am__append_101 = plugins/lookip/libstrongswan-lookip.la
+@USE_ERROR_NOTIFY_TRUE@am__append_102 = plugins/error_notify
+@MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE@am__append_103 = plugins/error_notify/libstrongswan-error-notify.la
+@USE_CERTEXPIRE_TRUE@am__append_104 = plugins/certexpire
+@MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE@am__append_105 = plugins/certexpire/libstrongswan-certexpire.la
+@USE_SYSTIME_FIX_TRUE@am__append_106 = plugins/systime_fix
+@MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE@am__append_107 = plugins/systime_fix/libstrongswan-systime-fix.la
+@USE_LED_TRUE@am__append_108 = plugins/led
+@MONOLITHIC_TRUE@@USE_LED_TRUE@am__append_109 = plugins/led/libstrongswan-led.la
+@USE_DUPLICHECK_TRUE@am__append_110 = plugins/duplicheck
+@MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE@am__append_111 = plugins/duplicheck/libstrongswan-duplicheck.la
+@USE_COUPLING_TRUE@am__append_112 = plugins/coupling
+@MONOLITHIC_TRUE@@USE_COUPLING_TRUE@am__append_113 = plugins/coupling/libstrongswan-coupling.la
+@USE_RADATTR_TRUE@am__append_114 = plugins/radattr
+@MONOLITHIC_TRUE@@USE_RADATTR_TRUE@am__append_115 = plugins/radattr/libstrongswan-radattr.la
+@USE_UCI_TRUE@am__append_116 = plugins/uci
+@MONOLITHIC_TRUE@@USE_UCI_TRUE@am__append_117 = plugins/uci/libstrongswan-uci.la
+@USE_ADDRBLOCK_TRUE@am__append_118 = plugins/addrblock
+@MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE@am__append_119 = plugins/addrblock/libstrongswan-addrblock.la
+@USE_UNITY_TRUE@am__append_120 = plugins/unity
+@MONOLITHIC_TRUE@@USE_UNITY_TRUE@am__append_121 = plugins/unity/libstrongswan-unity.la
+@USE_UNIT_TESTS_TRUE@am__append_122 = plugins/unit_tester
+@MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE@am__append_123 = plugins/unit_tester/libstrongswan-unit-tester.la
+@USE_XAUTH_GENERIC_TRUE@am__append_124 = plugins/xauth_generic
+@MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE@am__append_125 = plugins/xauth_generic/libstrongswan-xauth-generic.la
+@USE_XAUTH_EAP_TRUE@am__append_126 = plugins/xauth_eap
+@MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE@am__append_127 = plugins/xauth_eap/libstrongswan-xauth-eap.la
+@USE_XAUTH_PAM_TRUE@am__append_128 = plugins/xauth_pam
+@MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE@am__append_129 = plugins/xauth_pam/libstrongswan-xauth-pam.la
+@USE_XAUTH_NOAUTH_TRUE@am__append_130 = plugins/xauth_noauth
+@MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE@am__append_131 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
subdir = src/libcharon
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp
@@ -323,12 +325,12 @@ libcharon_la_DEPENDENCIES = \
$(am__append_29) $(am__append_31) $(am__append_33) \
$(am__append_35) $(am__append_37) $(am__append_39) \
$(am__append_41) $(am__append_43) $(am__append_45) \
- $(am__append_47) $(am__append_48) $(am__append_50) \
+ $(am__append_47) $(am__append_49) $(am__append_50) \
$(am__append_52) $(am__append_54) $(am__append_56) \
$(am__append_58) $(am__append_60) $(am__append_62) \
- $(am__append_64) $(am__append_66) $(am__append_67) \
- $(am__append_68) $(am__append_70) $(am__append_72) \
- $(am__append_73) $(am__append_75) $(am__append_77) \
+ $(am__append_64) $(am__append_66) $(am__append_68) \
+ $(am__append_69) $(am__append_70) $(am__append_72) \
+ $(am__append_74) $(am__append_75) $(am__append_77) \
$(am__append_79) $(am__append_81) $(am__append_83) \
$(am__append_85) $(am__append_87) $(am__append_89) \
$(am__append_91) $(am__append_93) $(am__append_95) \
@@ -337,7 +339,7 @@ libcharon_la_DEPENDENCIES = \
$(am__append_109) $(am__append_111) $(am__append_113) \
$(am__append_115) $(am__append_117) $(am__append_119) \
$(am__append_121) $(am__append_123) $(am__append_125) \
- $(am__append_127) $(am__append_129)
+ $(am__append_127) $(am__append_129) $(am__append_131)
am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
bus/listeners/listener.h bus/listeners/logger.h \
bus/listeners/file_logger.c bus/listeners/file_logger.h \
@@ -362,8 +364,9 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
encoding/payloads/eap_payload.c \
encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
encoding/payloads/encodings.h \
- encoding/payloads/encryption_payload.c \
- encoding/payloads/encryption_payload.h \
+ encoding/payloads/encrypted_payload.c \
+ encoding/payloads/encrypted_payload.h \
+ encoding/payloads/encrypted_fragment_payload.h \
encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
@@ -553,7 +556,7 @@ am_libcharon_la_OBJECTS = bus/bus.lo bus/listeners/file_logger.lo \
encoding/payloads/delete_payload.lo \
encoding/payloads/eap_payload.lo \
encoding/payloads/encodings.lo \
- encoding/payloads/encryption_payload.lo \
+ encoding/payloads/encrypted_payload.lo \
encoding/payloads/id_payload.lo \
encoding/payloads/ike_header.lo \
encoding/payloads/ke_payload.lo \
@@ -676,22 +679,23 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
plugins/socket_dynamic plugins/socket_win plugins/farp \
plugins/stroke plugins/vici plugins/smp plugins/sql \
plugins/dnscert plugins/ipseckey plugins/updown \
- plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \
- plugins/eap_sim_pcsc plugins/eap_simaka_sql \
- plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
- plugins/eap_aka plugins/eap_aka_3gpp2 plugins/eap_md5 \
- plugins/eap_gtc plugins/eap_mschapv2 plugins/eap_dynamic \
- plugins/eap_radius plugins/eap_tls plugins/eap_ttls \
- plugins/eap_peap plugins/eap_tnc plugins/tnc_ifmap \
- plugins/tnc_pdp plugins/medsrv plugins/medcli plugins/dhcp \
- plugins/osx_attr plugins/android_dns plugins/android_log \
- plugins/maemo plugins/ha plugins/kernel_libipsec \
- plugins/kernel_wfp plugins/kernel_iph plugins/whitelist \
- plugins/lookip plugins/error_notify plugins/certexpire \
- plugins/systime_fix plugins/led plugins/duplicheck \
- plugins/coupling plugins/radattr plugins/uci plugins/addrblock \
- plugins/unity plugins/unit_tester plugins/xauth_generic \
- plugins/xauth_eap plugins/xauth_pam plugins/xauth_noauth
+ plugins/ext_auth plugins/eap_identity plugins/eap_sim \
+ plugins/eap_sim_file plugins/eap_sim_pcsc \
+ plugins/eap_simaka_sql plugins/eap_simaka_pseudonym \
+ plugins/eap_simaka_reauth plugins/eap_aka \
+ plugins/eap_aka_3gpp2 plugins/eap_md5 plugins/eap_gtc \
+ plugins/eap_mschapv2 plugins/eap_dynamic plugins/eap_radius \
+ plugins/eap_tls plugins/eap_ttls plugins/eap_peap \
+ plugins/eap_tnc plugins/tnc_ifmap plugins/tnc_pdp \
+ plugins/medsrv plugins/medcli plugins/dhcp plugins/osx_attr \
+ plugins/android_dns plugins/android_log plugins/maemo \
+ plugins/ha plugins/kernel_libipsec plugins/kernel_wfp \
+ plugins/kernel_iph plugins/whitelist plugins/lookip \
+ plugins/error_notify plugins/certexpire plugins/systime_fix \
+ plugins/led plugins/duplicheck plugins/coupling \
+ plugins/radattr plugins/uci plugins/addrblock plugins/unity \
+ plugins/unit_tester plugins/xauth_generic plugins/xauth_eap \
+ plugins/xauth_pam plugins/xauth_noauth
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -749,6 +753,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -809,6 +814,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -874,6 +880,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -921,6 +929,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
@@ -954,8 +966,9 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
encoding/payloads/eap_payload.c \
encoding/payloads/eap_payload.h encoding/payloads/encodings.c \
encoding/payloads/encodings.h \
- encoding/payloads/encryption_payload.c \
- encoding/payloads/encryption_payload.h \
+ encoding/payloads/encrypted_payload.c \
+ encoding/payloads/encrypted_payload.h \
+ encoding/payloads/encrypted_fragment_payload.h \
encoding/payloads/id_payload.c encoding/payloads/id_payload.h \
encoding/payloads/ike_header.c encoding/payloads/ike_header.h \
encoding/payloads/ke_payload.c encoding/payloads/ke_payload.h \
@@ -1043,12 +1056,12 @@ libcharon_la_LIBADD = \
$(am__append_27) $(am__append_29) $(am__append_31) \
$(am__append_33) $(am__append_35) $(am__append_37) \
$(am__append_39) $(am__append_41) $(am__append_43) \
- $(am__append_45) $(am__append_47) $(am__append_48) \
+ $(am__append_45) $(am__append_47) $(am__append_49) \
$(am__append_50) $(am__append_52) $(am__append_54) \
$(am__append_56) $(am__append_58) $(am__append_60) \
$(am__append_62) $(am__append_64) $(am__append_66) \
- $(am__append_67) $(am__append_68) $(am__append_70) \
- $(am__append_72) $(am__append_73) $(am__append_75) \
+ $(am__append_68) $(am__append_69) $(am__append_70) \
+ $(am__append_72) $(am__append_74) $(am__append_75) \
$(am__append_77) $(am__append_79) $(am__append_81) \
$(am__append_83) $(am__append_85) $(am__append_87) \
$(am__append_89) $(am__append_91) $(am__append_93) \
@@ -1057,7 +1070,8 @@ libcharon_la_LIBADD = \
$(am__append_107) $(am__append_109) $(am__append_111) \
$(am__append_113) $(am__append_115) $(am__append_117) \
$(am__append_119) $(am__append_121) $(am__append_123) \
- $(am__append_125) $(am__append_127) $(am__append_129)
+ $(am__append_125) $(am__append_127) $(am__append_129) \
+ $(am__append_131)
EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \
@MONOLITHIC_FALSE@ $(am__append_10) $(am__append_12) \
@@ -1069,13 +1083,13 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_34) $(am__append_36) \
@MONOLITHIC_FALSE@ $(am__append_38) $(am__append_40) \
@MONOLITHIC_FALSE@ $(am__append_42) $(am__append_44) \
-@MONOLITHIC_FALSE@ $(am__append_46) $(am__append_49) \
+@MONOLITHIC_FALSE@ $(am__append_46) $(am__append_48) \
@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_53) \
@MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \
@MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61) \
@MONOLITHIC_FALSE@ $(am__append_63) $(am__append_65) \
-@MONOLITHIC_FALSE@ $(am__append_69) $(am__append_71) \
-@MONOLITHIC_FALSE@ $(am__append_74) $(am__append_76) \
+@MONOLITHIC_FALSE@ $(am__append_67) $(am__append_71) \
+@MONOLITHIC_FALSE@ $(am__append_73) $(am__append_76) \
@MONOLITHIC_FALSE@ $(am__append_78) $(am__append_80) \
@MONOLITHIC_FALSE@ $(am__append_82) $(am__append_84) \
@MONOLITHIC_FALSE@ $(am__append_86) $(am__append_88) \
@@ -1088,7 +1102,8 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_FALSE@ $(am__append_114) $(am__append_116) \
@MONOLITHIC_FALSE@ $(am__append_118) $(am__append_120) \
@MONOLITHIC_FALSE@ $(am__append_122) $(am__append_124) \
-@MONOLITHIC_FALSE@ $(am__append_126) $(am__append_128)
+@MONOLITHIC_FALSE@ $(am__append_126) $(am__append_128) \
+@MONOLITHIC_FALSE@ $(am__append_130)
# build optional plugins
########################
@@ -1102,13 +1117,13 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_34) $(am__append_36) \
@MONOLITHIC_TRUE@ $(am__append_38) $(am__append_40) \
@MONOLITHIC_TRUE@ $(am__append_42) $(am__append_44) \
-@MONOLITHIC_TRUE@ $(am__append_46) $(am__append_49) \
+@MONOLITHIC_TRUE@ $(am__append_46) $(am__append_48) \
@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_53) \
@MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \
@MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61) \
@MONOLITHIC_TRUE@ $(am__append_63) $(am__append_65) \
-@MONOLITHIC_TRUE@ $(am__append_69) $(am__append_71) \
-@MONOLITHIC_TRUE@ $(am__append_74) $(am__append_76) \
+@MONOLITHIC_TRUE@ $(am__append_67) $(am__append_71) \
+@MONOLITHIC_TRUE@ $(am__append_73) $(am__append_76) \
@MONOLITHIC_TRUE@ $(am__append_78) $(am__append_80) \
@MONOLITHIC_TRUE@ $(am__append_82) $(am__append_84) \
@MONOLITHIC_TRUE@ $(am__append_86) $(am__append_88) \
@@ -1121,7 +1136,8 @@ EXTRA_DIST = Android.mk
@MONOLITHIC_TRUE@ $(am__append_114) $(am__append_116) \
@MONOLITHIC_TRUE@ $(am__append_118) $(am__append_120) \
@MONOLITHIC_TRUE@ $(am__append_122) $(am__append_124) \
-@MONOLITHIC_TRUE@ $(am__append_126) $(am__append_128)
+@MONOLITHIC_TRUE@ $(am__append_126) $(am__append_128) \
+@MONOLITHIC_TRUE@ $(am__append_130)
all: all-recursive
.SUFFIXES:
@@ -1267,7 +1283,7 @@ encoding/payloads/eap_payload.lo: encoding/payloads/$(am__dirstamp) \
encoding/payloads/$(DEPDIR)/$(am__dirstamp)
encoding/payloads/encodings.lo: encoding/payloads/$(am__dirstamp) \
encoding/payloads/$(DEPDIR)/$(am__dirstamp)
-encoding/payloads/encryption_payload.lo: \
+encoding/payloads/encrypted_payload.lo: \
encoding/payloads/$(am__dirstamp) \
encoding/payloads/$(DEPDIR)/$(am__dirstamp)
encoding/payloads/id_payload.lo: encoding/payloads/$(am__dirstamp) \
@@ -1619,7 +1635,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/delete_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/eap_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/encodings.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/encryption_payload.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/encrypted_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/endpoint_notify.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/fragment_payload.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@encoding/payloads/$(DEPDIR)/hash_payload.Plo@am__quote@
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index d1c138cd1..cb59f976b 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -755,7 +755,7 @@ METHOD(bus_t, ike_rekey, void,
this->mutex->unlock(this->mutex);
}
-METHOD(bus_t, ike_reestablish, void,
+METHOD(bus_t, ike_reestablish_pre, void,
private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
{
enumerator_t *enumerator;
@@ -766,12 +766,40 @@ METHOD(bus_t, ike_reestablish, void,
enumerator = this->listeners->create_enumerator(this->listeners);
while (enumerator->enumerate(enumerator, &entry))
{
- if (entry->calling || !entry->listener->ike_reestablish)
+ if (entry->calling || !entry->listener->ike_reestablish_pre)
{
continue;
}
entry->calling++;
- keep = entry->listener->ike_reestablish(entry->listener, old, new);
+ keep = entry->listener->ike_reestablish_pre(entry->listener, old, new);
+ entry->calling--;
+ if (!keep)
+ {
+ unregister_listener(this, entry, enumerator);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+}
+
+METHOD(bus_t, ike_reestablish_post, void,
+ private_bus_t *this, ike_sa_t *old, ike_sa_t *new, bool initiated)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ bool keep;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->listeners->create_enumerator(this->listeners);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->calling || !entry->listener->ike_reestablish_post)
+ {
+ continue;
+ }
+ entry->calling++;
+ keep = entry->listener->ike_reestablish_post(entry->listener, old, new,
+ initiated);
entry->calling--;
if (!keep)
{
@@ -978,7 +1006,8 @@ bus_t *bus_create()
.child_keys = _child_keys,
.ike_updown = _ike_updown,
.ike_rekey = _ike_rekey,
- .ike_reestablish = _ike_reestablish,
+ .ike_reestablish_pre = _ike_reestablish_pre,
+ .ike_reestablish_post = _ike_reestablish_post,
.child_updown = _child_updown,
.child_rekey = _child_rekey,
.authorize = _authorize,
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
index 1d708c5a5..e1d221ca5 100644
--- a/src/libcharon/bus/bus.h
+++ b/src/libcharon/bus/bus.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2006-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -101,9 +101,11 @@ enum alert_t {
/** received IKE message with invalid body, argument is message_t*,
* followed by a status_t result returned by message_t.parse_body(). */
ALERT_PARSE_ERROR_BODY,
- /** sending a retransmit for a message, argument is packet_t */
+ /** sending a retransmit for a message, argument is packet_t, if the message
+ * got fragmented only the first fragment is passed */
ALERT_RETRANSMIT_SEND,
- /** sending retransmits timed out, argument is packet_t, if available */
+ /** sending retransmits timed out, argument is packet_t, if available and if
+ * the message got fragmented only the first fragment is passed */
ALERT_RETRANSMIT_SEND_TIMEOUT,
/** received a retransmit for a message, argument is message_t */
ALERT_RETRANSMIT_RECEIVE,
@@ -380,12 +382,23 @@ struct bus_t {
void (*ike_rekey)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
/**
- * IKE_SA reestablishing hook.
+ * IKE_SA reestablishing hook (before resolving hosts).
*
* @param old reestablished and obsolete IKE_SA
* @param new new IKE_SA replacing old
*/
- void (*ike_reestablish)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
+ void (*ike_reestablish_pre)(bus_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
+ * IKE_SA reestablishing hook (after configuring and initiating the new
+ * IKE_SA).
+ *
+ * @param old reestablished and obsolete IKE_SA
+ * @param new new IKE_SA replacing old
+ * @param initiated TRUE if initiated successfully, FALSE otherwise
+ */
+ void (*ike_reestablish_post)(bus_t *this, ike_sa_t *old, ike_sa_t *new,
+ bool initiated);
/**
* CHILD_SA up/down hook.
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
index abcc765e5..0910cb361 100644
--- a/src/libcharon/bus/listeners/listener.h
+++ b/src/libcharon/bus/listeners/listener.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2011-2014 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -129,14 +130,29 @@ struct listener_t {
/**
* Hook called when an initiator reestablishes an IKE_SA.
*
+ * This is invoked right after creating the new IKE_SA and setting the
+ * peer_cfg (and the old hosts), but before resolving the hosts anew.
+ * It is not invoked on the responder.
+ *
+ * @param old IKE_SA getting reestablished (is destroyed)
+ * @param new new IKE_SA replacing old (gets established)
+ * @return TRUE to stay registered, FALSE to unregister
+ */
+ bool (*ike_reestablish_pre)(listener_t *this, ike_sa_t *old, ike_sa_t *new);
+
+ /**
+ * Hook called when an initiator reestablishes an IKE_SA.
+ *
* This is invoked right before the new IKE_SA is checked in after
* initiating it. It is not invoked on the responder.
*
* @param old IKE_SA getting reestablished (is destroyed)
* @param new new IKE_SA replacing old (gets established)
+ * @param initiated TRUE if initiation was successful, FALSE otherwise
* @return TRUE to stay registered, FALSE to unregister
*/
- bool (*ike_reestablish)(listener_t *this, ike_sa_t *old, ike_sa_t *new);
+ bool (*ike_reestablish_post)(listener_t *this, ike_sa_t *old,
+ ike_sa_t *new, bool initiated);
/**
* Hook called when a CHILD_SA gets up or down.
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 7e4a1433d..ed7c0d406 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -163,6 +163,11 @@ METHOD(child_cfg_t, add_proposal, void,
}
}
+static bool match_proposal(proposal_t *item, proposal_t *proposal)
+{
+ return item->equals(item, proposal);
+}
+
METHOD(child_cfg_t, get_proposals, linked_list_t*,
private_child_cfg_t *this, bool strip_dh)
{
@@ -178,6 +183,12 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*,
{
current->strip_dh(current, MODP_NONE);
}
+ if (proposals->find_first(proposals, (linked_list_match_t)match_proposal,
+ NULL, current) == SUCCESS)
+ {
+ current->destroy(current);
+ continue;
+ }
proposals->insert_last(proposals, current);
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 4d881cd2f..50d3c6f66 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -337,7 +337,7 @@ static bool algo_list_equals(private_proposal_t *this, proposal_t *other,
break;
}
}
- if (e2->enumerate(e2, &alg2, ks2))
+ if (e2->enumerate(e2, &alg2, &ks2))
{
/* other has more algs */
equals = FALSE;
@@ -594,7 +594,7 @@ METHOD(proposal_t, destroy, void,
}
/*
- * Describtion in header-file
+ * Described in header
*/
proposal_t *proposal_create(protocol_id_t protocol, u_int number)
{
@@ -787,7 +787,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
}
/*
- * Describtion in header-file
+ * Described in header
*/
proposal_t *proposal_create_default(protocol_id_t protocol)
{
@@ -826,7 +826,7 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
}
/*
- * Describtion in header-file
+ * Described in header
*/
proposal_t *proposal_create_default_aead(protocol_id_t protocol)
{
@@ -853,7 +853,7 @@ proposal_t *proposal_create_default_aead(protocol_id_t protocol)
}
/*
- * Describtion in header-file
+ * Described in header
*/
proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
{
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index a89995a51..3ae7c4e6f 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -593,7 +593,7 @@ METHOD(daemon_t, initialize, bool,
PLUGIN_DEPENDS(CUSTOM, "socket"),
};
lib->plugins->add_static_features(lib->plugins, lib->ns, features,
- countof(features), TRUE);
+ countof(features), TRUE, NULL, NULL);
/* load plugins, further infrastructure may need it */
if (!lib->plugins->load(lib->plugins, plugins))
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 0f5f40ada..cb6c97f25 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2013 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2006 Daniel Roethlisberger
@@ -23,6 +23,8 @@
#include "message.h"
#include <library.h>
+#include <bio/bio_writer.h>
+#include <collections/array.h>
#include <daemon.h>
#include <sa/ikev1/keymat_v1.h>
#include <encoding/generator.h>
@@ -30,9 +32,11 @@
#include <encoding/payloads/encodings.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/hash_payload.h>
-#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/encrypted_payload.h>
+#include <encoding/payloads/encrypted_fragment_payload.h>
#include <encoding/payloads/unknown_payload.h>
#include <encoding/payloads/cp_payload.h>
+#include <encoding/payloads/fragment_payload.h>
/**
* Max number of notify payloads per IKEv2 message
@@ -802,6 +806,30 @@ static message_rule_t message_rules[] = {
#endif /* USE_IKEV1 */
};
+/**
+ * Data for fragment reassembly.
+ */
+typedef struct {
+
+ /**
+ * For IKEv1 the number of the last fragment (in case we receive them out
+ * of order), since the first one starts with 1 this defines the number of
+ * fragments we expect.
+ * For IKEv2 we store the total number of fragment we received last.
+ */
+ u_int16_t last;
+
+ /**
+ * Length of all currently received fragments.
+ */
+ size_t len;
+
+ /**
+ * Maximum length of a fragmented packet.
+ */
+ size_t max_packet;
+
+} fragment_data_t;
typedef struct private_message_t private_message_t;
@@ -876,6 +904,12 @@ struct private_message_t {
packet_t *packet;
/**
+ * Array of generated fragments (if any), as packet_t*.
+ * If defragmenting (i.e. frag != NULL) this contains fragment_t*
+ */
+ array_t *fragments;
+
+ /**
* Linked List where payload data are stored in.
*/
linked_list_t *payloads;
@@ -889,9 +923,46 @@ struct private_message_t {
* The message rule for this message instance
*/
message_rule_t *rule;
+
+ /**
+ * Data used to reassemble a fragmented message
+ */
+ fragment_data_t *frag;
};
/**
+ * Maximum number of fragments we will handle
+ */
+#define MAX_FRAGMENTS 255
+
+/**
+ * A single fragment within a fragmented message
+ */
+typedef struct {
+
+ /** fragment number */
+ u_int8_t num;
+
+ /** fragment data */
+ chunk_t data;
+
+} fragment_t;
+
+static void fragment_destroy(fragment_t *this)
+{
+ chunk_free(&this->data);
+ free(this);
+}
+
+static void reset_defrag(private_message_t *this)
+{
+ array_destroy_function(this->fragments, (void*)fragment_destroy, NULL);
+ this->fragments = NULL;
+ this->frag->last = 0;
+ this->frag->len = 0;
+}
+
+/**
* Get the message rule that applies to this message
*/
static message_rule_t* get_message_rule(private_message_t *this)
@@ -1049,6 +1120,12 @@ METHOD(message_t, is_encoded, bool,
return this->packet->get_data(this->packet).ptr != NULL;
}
+METHOD(message_t, is_fragmented, bool,
+ private_message_t *this)
+{
+ return array_count(this->fragments) > 0;
+}
+
METHOD(message_t, add_payload, void,
private_message_t *this, payload_t *payload)
{
@@ -1330,6 +1407,12 @@ static char* get_string(private_message_t *this, char *buf, int len)
return buf;
}
+METHOD(message_t, disable_sort, void,
+ private_message_t *this)
+{
+ this->sort_disabled = TRUE;
+}
+
/**
* reorder payloads depending on reordering rules
*/
@@ -1339,6 +1422,8 @@ static void order_payloads(private_message_t *this)
payload_t *payload;
int i;
+ DBG2(DBG_ENC, "order payloads in message");
+
/* move to temp list */
list = linked_list_create();
while (this->payloads->remove_last(this->payloads,
@@ -1392,29 +1477,42 @@ static void order_payloads(private_message_t *this)
}
/**
- * Wrap payloads in an encryption payload
+ * Wrap payloads in an encrypted payload
*/
-static encryption_payload_t* wrap_payloads(private_message_t *this)
+static encrypted_payload_t* wrap_payloads(private_message_t *this)
{
- encryption_payload_t *encryption;
+ encrypted_payload_t *encrypted = NULL;
linked_list_t *payloads;
payload_t *current;
- /* copy all payloads in a temporary list */
+ /* move all payloads to a temporary list */
payloads = linked_list_create();
while (this->payloads->remove_first(this->payloads,
(void**)&current) == SUCCESS)
{
- payloads->insert_last(payloads, current);
+ if (current->get_type(current) == PLV2_FRAGMENT)
+ { /* treat encrypted fragment payload as encrypted payload */
+ encrypted = (encrypted_payload_t*)current;
+ }
+ else
+ {
+ payloads->insert_last(payloads, current);
+ }
+ }
+ if (encrypted)
+ { /* simply adopt all the unencrypted payloads */
+ this->payloads->destroy(this->payloads);
+ this->payloads = payloads;
+ return encrypted;
}
if (this->is_encrypted)
{
- encryption = encryption_payload_create(PLV1_ENCRYPTED);
+ encrypted = encrypted_payload_create(PLV1_ENCRYPTED);
}
else
{
- encryption = encryption_payload_create(PLV2_ENCRYPTED);
+ encrypted = encrypted_payload_create(PLV2_ENCRYPTED);
}
while (payloads->remove_first(payloads, (void**)&current) == SUCCESS)
{
@@ -1432,7 +1530,7 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
{ /* encryption is forced for IKEv1 */
DBG2(DBG_ENC, "insert payload %N into encrypted payload",
payload_type_names, type);
- encryption->add_payload(encryption, current);
+ encrypted->add_payload(encrypted, current);
}
else
{
@@ -1443,31 +1541,71 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
}
payloads->destroy(payloads);
- return encryption;
+ return encrypted;
}
-METHOD(message_t, disable_sort, void,
- private_message_t *this)
+/**
+ * Creates the IKE header for this message
+ */
+static ike_header_t *create_header(private_message_t *this)
{
- this->sort_disabled = TRUE;
+ ike_header_t *ike_header;
+ bool *reserved;
+ int i;
+
+ ike_header = ike_header_create_version(this->major_version,
+ this->minor_version);
+ ike_header->set_exchange_type(ike_header, this->exchange_type);
+ ike_header->set_message_id(ike_header, this->message_id);
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ ike_header->set_response_flag(ike_header, !this->is_request);
+ ike_header->set_version_flag(ike_header, this->version_flag);
+ ike_header->set_initiator_flag(ike_header,
+ this->ike_sa_id->is_initiator(this->ike_sa_id));
+ }
+ else
+ {
+ ike_header->set_encryption_flag(ike_header, this->is_encrypted);
+ }
+ ike_header->set_initiator_spi(ike_header,
+ this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
+ ike_header->set_responder_spi(ike_header,
+ this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+
+ for (i = 0; i < countof(this->reserved); i++)
+ {
+ reserved = payload_get_field(&ike_header->payload_interface,
+ RESERVED_BIT, i);
+ if (reserved)
+ {
+ *reserved = this->reserved[i];
+ }
+ }
+ return ike_header;
}
-METHOD(message_t, generate, status_t,
- private_message_t *this, keymat_t *keymat, packet_t **packet)
+/**
+ * Generates the message, if needed, wraps the payloads in an encrypted payload.
+ *
+ * The generator and the possible enrypted payload are returned. The latter
+ * is not yet encrypted (but the transform is set). It is also not added to
+ * the payload list (so unless there are unencrypted payloads that list will
+ * be empty afterwards).
+ */
+static status_t generate_message(private_message_t *this, keymat_t *keymat,
+ generator_t **out_generator, encrypted_payload_t **encrypted)
{
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
generator_t *generator;
- ike_header_t *ike_header;
- payload_t *payload, *next;
- encryption_payload_t *encryption = NULL;
payload_type_t next_type;
enumerator_t *enumerator;
aead_t *aead = NULL;
- chunk_t chunk, hash = chunk_empty;
+ chunk_t hash = chunk_empty;
char str[BUF_LEN];
- u_int32_t *lenpos;
- bool encrypted = FALSE, *reserved;
- int i;
+ ike_header_t *ike_header;
+ payload_t *payload, *next;
+ bool encrypting = FALSE;
if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED)
{
@@ -1493,6 +1631,7 @@ METHOD(message_t, generate, status_t,
{
order_payloads(this);
}
+
if (keymat && keymat->get_version(keymat) == IKEV1)
{
/* get a hash for this message, if any is required */
@@ -1505,16 +1644,17 @@ METHOD(message_t, generate, status_t,
this->payloads->insert_first(this->payloads, hash_payload);
if (this->exchange_type == INFORMATIONAL_V1)
{
- this->is_encrypted = encrypted = TRUE;
+ this->is_encrypted = encrypting = TRUE;
}
chunk_free(&hash);
}
}
+
if (this->major_version == IKEV2_MAJOR_VERSION)
{
- encrypted = this->rule->encrypted;
+ encrypting = this->rule->encrypted;
}
- else if (!encrypted)
+ else if (!encrypting)
{
/* If at least one payload requires encryption, encrypt the message.
* If no key material is available, the flag will be reset below. */
@@ -1526,7 +1666,7 @@ METHOD(message_t, generate, status_t,
rule = get_payload_rule(this, payload->get_type(payload));
if (rule && rule->encrypted)
{
- this->is_encrypted = encrypted = TRUE;
+ this->is_encrypted = encrypting = TRUE;
break;
}
}
@@ -1539,9 +1679,10 @@ METHOD(message_t, generate, status_t,
{
aead = keymat->get_aead(keymat, FALSE);
}
- if (aead && encrypted)
+ if (aead && encrypting)
{
- encryption = wrap_payloads(this);
+ *encrypted = wrap_payloads(this);
+ (*encrypted)->set_transform(*encrypted, aead);
}
else
{
@@ -1549,39 +1690,9 @@ METHOD(message_t, generate, status_t,
this->is_encrypted = FALSE;
}
- ike_header = ike_header_create_version(this->major_version,
- this->minor_version);
- ike_header->set_exchange_type(ike_header, this->exchange_type);
- ike_header->set_message_id(ike_header, this->message_id);
- if (this->major_version == IKEV2_MAJOR_VERSION)
- {
- ike_header->set_response_flag(ike_header, !this->is_request);
- ike_header->set_version_flag(ike_header, this->version_flag);
- ike_header->set_initiator_flag(ike_header,
- this->ike_sa_id->is_initiator(this->ike_sa_id));
- }
- else
- {
- ike_header->set_encryption_flag(ike_header, this->is_encrypted);
- }
- ike_header->set_initiator_spi(ike_header,
- this->ike_sa_id->get_initiator_spi(this->ike_sa_id));
- ike_header->set_responder_spi(ike_header,
- this->ike_sa_id->get_responder_spi(this->ike_sa_id));
-
- for (i = 0; i < countof(this->reserved); i++)
- {
- reserved = payload_get_field(&ike_header->payload_interface,
- RESERVED_BIT, i);
- if (reserved)
- {
- *reserved = this->reserved[i];
- }
- }
-
- generator = generator_create();
-
/* generate all payloads with proper next type */
+ *out_generator = generator = generator_create();
+ ike_header = create_header(this);
payload = (payload_t*)ike_header;
enumerator = create_payload_enumerator(this);
while (enumerator->enumerate(enumerator, &next))
@@ -1591,53 +1702,71 @@ METHOD(message_t, generate, status_t,
payload = next;
}
enumerator->destroy(enumerator);
+
+ next_type = PL_NONE;
if (this->is_encrypted)
{ /* for encrypted IKEv1 messages */
- next_type = encryption->payload_interface.get_next_type(
- (payload_t*)encryption);
+ next_type = (*encrypted)->payload_interface.get_next_type(
+ (payload_t*)*encrypted);
}
- else
- {
- next_type = encryption ? PLV2_ENCRYPTED : PL_NONE;
+ else if (*encrypted)
+ { /* use proper IKEv2 encrypted (fragment) payload type */
+ next_type = (*encrypted)->payload_interface.get_type(
+ (payload_t*)*encrypted);
}
payload->set_next_type(payload, next_type);
generator->generate_payload(generator, payload);
ike_header->destroy(ike_header);
+ return SUCCESS;
+}
- if (encryption)
- { /* set_transform() has to be called before get_length() */
- encryption->set_transform(encryption, aead);
+/**
+ * Encrypts and adds the encrypted payload (if any) to the payload list and
+ * finalizes the message generation. Destroys the given generator.
+ */
+static status_t finalize_message(private_message_t *this, keymat_t *keymat,
+ generator_t *generator, encrypted_payload_t *encrypted)
+{
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
+ chunk_t chunk;
+ u_int32_t *lenpos;
+
+ if (encrypted)
+ {
if (this->is_encrypted)
{ /* for IKEv1 instead of associated data we provide the IV */
if (!keymat_v1->get_iv(keymat_v1, this->message_id, &chunk))
{
generator->destroy(generator);
+ encrypted->destroy(encrypted);
return FAILED;
}
}
else
- { /* build associated data (without header of encryption payload) */
+ { /* build associated data (without header of encrypted payload) */
chunk = generator->get_chunk(generator, &lenpos);
- /* fill in length, including encryption payload */
- htoun32(lenpos, chunk.len + encryption->get_length(encryption));
+ /* fill in length, including encrypted payload */
+ htoun32(lenpos, chunk.len + encrypted->get_length(encrypted));
}
- this->payloads->insert_last(this->payloads, encryption);
- if (encryption->encrypt(encryption, this->message_id, chunk) != SUCCESS)
+ this->payloads->insert_last(this->payloads, encrypted);
+ if (encrypted->encrypt(encrypted, this->message_id, chunk) != SUCCESS)
{
generator->destroy(generator);
return INVALID_STATE;
}
- generator->generate_payload(generator, &encryption->payload_interface);
+ generator->generate_payload(generator, &encrypted->payload_interface);
}
chunk = generator->get_chunk(generator, &lenpos);
htoun32(lenpos, chunk.len);
this->packet->set_data(this->packet, chunk_clone(chunk));
- if (this->is_encrypted)
+ if (this->is_encrypted && this->exchange_type != INFORMATIONAL_V1)
{
/* update the IV for the next IKEv1 message */
chunk_t last_block;
+ aead_t *aead;
size_t bs;
+ aead = keymat->get_aead(keymat, FALSE);
bs = aead->get_block_size(aead);
last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
if (!keymat_v1->update_iv(keymat_v1, this->message_id, last_block) ||
@@ -1648,30 +1777,301 @@ METHOD(message_t, generate, status_t,
}
}
generator->destroy(generator);
- *packet = this->packet->clone(this->packet);
return SUCCESS;
}
-METHOD(message_t, get_packet, packet_t*,
- private_message_t *this)
+METHOD(message_t, generate, status_t,
+ private_message_t *this, keymat_t *keymat, packet_t **packet)
{
- if (this->packet == NULL)
+ generator_t *generator = NULL;
+ encrypted_payload_t *encrypted = NULL;
+ status_t status;
+
+ status = generate_message(this, keymat, &generator, &encrypted);
+ if (status != SUCCESS)
{
- return NULL;
+ DESTROY_IF(generator);
+ return status;
+ }
+ status = finalize_message(this, keymat, generator, encrypted);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ if (packet)
+ {
+ *packet = this->packet->clone(this->packet);
+ }
+ return SUCCESS;
+}
+
+/**
+ * Creates a (basic) clone of the given message
+ */
+static message_t *clone_message(private_message_t *this)
+{
+ message_t *message;
+ host_t *src, *dst;
+
+ src = this->packet->get_source(this->packet);
+ dst = this->packet->get_destination(this->packet);
+
+ message = message_create(this->major_version, this->minor_version);
+ message->set_ike_sa_id(message, this->ike_sa_id);
+ message->set_message_id(message, this->message_id);
+ message->set_request(message, this->is_request);
+ message->set_source(message, src->clone(src));
+ message->set_destination(message, dst->clone(dst));
+ message->set_exchange_type(message, this->exchange_type);
+ memcpy(((private_message_t*)message)->reserved, this->reserved,
+ sizeof(this->reserved));
+ return message;
+}
+
+/**
+ * Create a single fragment with the given data
+ */
+static message_t *create_fragment(private_message_t *this, payload_type_t next,
+ u_int16_t num, u_int16_t count, chunk_t data)
+{
+ enumerator_t *enumerator;
+ payload_t *fragment, *payload;
+ message_t *message;
+ peer_cfg_t *peer_cfg;
+ ike_sa_t *ike_sa;
+
+ message = clone_message(this);
+ if (this->major_version == IKEV1_MAJOR_VERSION)
+ {
+ /* other implementations seem to just use 0 as message ID, so here we go */
+ message->set_message_id(message, 0);
+ /* always use the initial message type for fragments, even for quick mode
+ * or transaction messages. */
+ ike_sa = charon->bus->get_sa(charon->bus);
+ if (ike_sa && (peer_cfg = ike_sa->get_peer_cfg(ike_sa)) &&
+ peer_cfg->use_aggressive(peer_cfg))
+ {
+ message->set_exchange_type(message, AGGRESSIVE);
+ }
+ else
+ {
+ message->set_exchange_type(message, ID_PROT);
+ }
+ fragment = (payload_t*)fragment_payload_create_from_data(
+ num, num == count, data);
+ }
+ else
+ {
+ fragment = (payload_t*)encrypted_fragment_payload_create_from_data(
+ num, count, data);
+ if (num == 1)
+ {
+ /* only in the first fragment is this set to the type of the first
+ * payload in the encrypted payload */
+ fragment->set_next_type(fragment, next);
+ /* move unencrypted payloads to the first fragment */
+ enumerator = this->payloads->create_enumerator(this->payloads);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != PLV2_ENCRYPTED)
+ {
+ this->payloads->remove_at(this->payloads, enumerator);
+ message->add_payload(message, payload);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ }
+ message->add_payload(message, (payload_t*)fragment);
+ return message;
+}
+
+/**
+ * Destroy all fragments
+ */
+static void clear_fragments(private_message_t *this)
+{
+ array_destroy_offset(this->fragments, offsetof(packet_t, destroy));
+ this->fragments = NULL;
+}
+
+/**
+ * Reduce the fragment length but ensure it stays > 0
+ */
+#define REDUCE_FRAG_LEN(fl, amount) ({ \
+ fl = max(1, (ssize_t)fl - (amount)); \
+})
+
+METHOD(message_t, fragment, status_t,
+ private_message_t *this, keymat_t *keymat, size_t frag_len,
+ enumerator_t **fragments)
+{
+ encrypted_payload_t *encrypted = NULL;
+ generator_t *generator = NULL;
+ message_t *fragment;
+ packet_t *packet;
+ payload_type_t next = PL_NONE;
+ u_int16_t num, count;
+ host_t *src, *dst;
+ chunk_t data;
+ status_t status;
+ u_int32_t *lenpos;
+ size_t len;
+
+ src = this->packet->get_source(this->packet);
+ dst = this->packet->get_destination(this->packet);
+ if (!frag_len)
+ {
+ frag_len = (src->get_family(src) == AF_INET) ? 576 : 1280;
+ }
+ /* frag_len is the complete IP datagram length, account for overhead (we
+ * assume no IP options/extension headers are used) */
+ REDUCE_FRAG_LEN(frag_len, (src->get_family(src) == AF_INET) ? 20 : 40);
+ /* 8 (UDP header) */
+ REDUCE_FRAG_LEN(frag_len, 8);
+ if (dst->get_port(dst) != IKEV2_UDP_PORT &&
+ src->get_port(src) != IKEV2_UDP_PORT)
+ { /* reduce length due to non-ESP marker */
+ REDUCE_FRAG_LEN(frag_len, 4);
+ }
+
+ if (is_encoded(this))
+ {
+ if (this->major_version == IKEV2_MAJOR_VERSION)
+ {
+ encrypted = (encrypted_payload_t*)get_payload(this, PLV2_ENCRYPTED);
+ }
+ data = this->packet->get_data(this->packet);
+ len = data.len;
+ }
+ else
+ {
+ status = generate_message(this, keymat, &generator, &encrypted);
+ if (status != SUCCESS)
+ {
+ DESTROY_IF(generator);
+ return status;
+ }
+ data = generator->get_chunk(generator, &lenpos);
+ len = data.len + (encrypted ? encrypted->get_length(encrypted) : 0);
+ }
+
+ /* check if we actually need to fragment the message and if we have an
+ * encrypted payload for IKEv2 */
+ if (len <= frag_len ||
+ (this->major_version == IKEV2_MAJOR_VERSION && !encrypted))
+ {
+ if (generator)
+ {
+ status = finalize_message(this, keymat, generator, encrypted);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ }
+ *fragments = enumerator_create_single(this->packet, NULL);
+ return SUCCESS;
+ }
+
+ /* frag_len denoted the maximum IKE message size so far, later on it will
+ * denote the maximum content size of a fragment payload, therefore,
+ * account for IKE header */
+ REDUCE_FRAG_LEN(frag_len, 28);
+
+ if (this->major_version == IKEV1_MAJOR_VERSION)
+ {
+ if (generator)
+ {
+ status = finalize_message(this, keymat, generator, encrypted);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ data = this->packet->get_data(this->packet);
+ generator = NULL;
+ }
+ /* overhead for the fragmentation payload header */
+ REDUCE_FRAG_LEN(frag_len, 8);
}
+ else
+ {
+ aead_t *aead;
+
+ if (generator)
+ {
+ generator->destroy(generator);
+ generator = generator_create();
+ }
+ else
+ { /* do not log again if it was generated previously */
+ generator = generator_create_no_dbg();
+ }
+ next = encrypted->payload_interface.get_next_type((payload_t*)encrypted);
+ encrypted->generate_payloads(encrypted, generator);
+ data = generator->get_chunk(generator, &lenpos);
+ if (!is_encoded(this))
+ {
+ encrypted->destroy(encrypted);
+ }
+ aead = keymat->get_aead(keymat, FALSE);
+ /* overhead for the encrypted fragment payload */
+ REDUCE_FRAG_LEN(frag_len, aead->get_iv_size(aead));
+ REDUCE_FRAG_LEN(frag_len, aead->get_icv_size(aead));
+ /* header */
+ REDUCE_FRAG_LEN(frag_len, 8);
+ /* padding and padding length */
+ frag_len = round_down(frag_len, aead->get_block_size(aead));
+ REDUCE_FRAG_LEN(frag_len, 1);
+ /* TODO-FRAG: if there are unencrypted payloads, should we account for
+ * their length in the first fragment? we still would have to add
+ * an encrypted fragment payload (albeit empty), even so we couldn't
+ * prevent IP fragmentation in every case */
+ }
+
+ count = data.len / frag_len + (data.len % frag_len ? 1 : 0);
+ this->fragments = array_create(0, count);
+ DBG1(DBG_ENC, "splitting IKE message with length of %zu bytes into "
+ "%hu fragments", len, count);
+ for (num = 1; num <= count; num++)
+ {
+ len = min(data.len, frag_len);
+ fragment = create_fragment(this, next, num, count,
+ chunk_create(data.ptr, len));
+ status = fragment->generate(fragment, keymat, &packet);
+ fragment->destroy(fragment);
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_ENC, "failed to generate IKE fragment");
+ clear_fragments(this);
+ DESTROY_IF(generator);
+ return FAILED;
+ }
+ array_insert(this->fragments, ARRAY_TAIL, packet);
+ data = chunk_skip(data, len);
+ }
+ *fragments = array_create_enumerator(this->fragments);
+ DESTROY_IF(generator);
+ return SUCCESS;
+}
+
+METHOD(message_t, get_packet, packet_t*,
+ private_message_t *this)
+{
return this->packet->clone(this->packet);
}
METHOD(message_t, get_packet_data, chunk_t,
private_message_t *this)
{
- if (this->packet == NULL)
- {
- return chunk_empty;
- }
return this->packet->get_data(this->packet);
}
+METHOD(message_t, get_fragments, enumerator_t*,
+ private_message_t *this)
+{
+ return array_create_enumerator(this->fragments);
+}
+
METHOD(message_t, parse_header, status_t,
private_message_t *this)
{
@@ -1682,6 +2082,10 @@ METHOD(message_t, parse_header, status_t,
DBG2(DBG_ENC, "parsing header of message");
+ if (!this->parser)
+ { /* reassembled IKEv2 message, header is inherited from fragments */
+ return SUCCESS;
+ }
this->parser->reset_context(this->parser);
status = this->parser->parse_payload(this->parser, PL_HEADER,
(payload_t**)&ike_header);
@@ -1723,7 +2127,7 @@ METHOD(message_t, parse_header, status_t,
this->first_payload = ike_header->payload_interface.get_next_type(
&ike_header->payload_interface);
if (this->first_payload == PLV1_FRAGMENT && this->is_encrypted)
- { /* racoon sets the encryted bit when sending a fragment, but these
+ { /* racoon sets the encrypted bit when sending a fragment, but these
* messages are really not encrypted */
this->is_encrypted = FALSE;
}
@@ -1780,9 +2184,9 @@ static status_t parse_payloads(private_message_t *this)
status_t status;
if (this->is_encrypted)
- { /* wrap the whole encrypted IKEv1 message in a special encryption
+ { /* wrap the whole encrypted IKEv1 message in a special encrypted
* payload which is then handled just like a regular payload */
- encryption_payload_t *encryption;
+ encrypted_payload_t *encryption;
status = this->parser->parse_payload(this->parser, PLV1_ENCRYPTED,
(payload_t**)&encryption);
@@ -1824,9 +2228,9 @@ static status_t parse_payloads(private_message_t *this)
payload_type_names, type);
this->payloads->insert_last(this->payloads, payload);
- /* an encrypted payload is the last one, so STOP here. decryption is
- * done later */
- if (type == PLV2_ENCRYPTED)
+ /* an encrypted (fragment) payload MUST be the last one, so STOP here.
+ * decryption is done later */
+ if (type == PLV2_ENCRYPTED || type == PLV2_FRAGMENT)
{
DBG2(DBG_ENC, "%N payload found, stop parsing",
payload_type_names, type);
@@ -1841,7 +2245,7 @@ static status_t parse_payloads(private_message_t *this)
* Decrypt an encrypted payload and extract all contained payloads.
*/
static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
- payload_t *previous, encryption_payload_t *encryption)
+ payload_t *previous, encrypted_payload_t *encryption)
{
payload_t *encrypted;
payload_type_t type;
@@ -1861,43 +2265,52 @@ static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
DBG1(DBG_ENC, "found encrypted payload, but no transform set");
return INVALID_ARG;
}
- bs = aead->get_block_size(aead);
- encryption->set_transform(encryption, aead);
- chunk = this->packet->get_data(this->packet);
- if (chunk.len < encryption->get_length(encryption) ||
- chunk.len < bs)
+ if (!this->parser)
{
- DBG1(DBG_ENC, "invalid payload length");
- return VERIFY_ERROR;
+ /* reassembled IKEv2 messages are already decrypted, we still call
+ * decrypt() to parse the contained payloads */
+ status = encryption->decrypt(encryption, chunk_empty);
}
- if (keymat->get_version(keymat) == IKEV1)
- { /* instead of associated data we provide the IV, we also update
- * the IV with the last encrypted block */
- keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
- chunk_t iv;
-
- if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv))
+ else
+ {
+ bs = aead->get_block_size(aead);
+ encryption->set_transform(encryption, aead);
+ chunk = this->packet->get_data(this->packet);
+ if (chunk.len < encryption->get_length(encryption) ||
+ chunk.len < bs)
{
- status = encryption->decrypt(encryption, iv);
- if (status == SUCCESS)
+ DBG1(DBG_ENC, "invalid payload length");
+ return VERIFY_ERROR;
+ }
+ if (keymat->get_version(keymat) == IKEV1)
+ { /* instead of associated data we provide the IV, we also update
+ * the IV with the last encrypted block */
+ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
+ chunk_t iv;
+
+ if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv))
{
- if (!keymat_v1->update_iv(keymat_v1, this->message_id,
- chunk_create(chunk.ptr + chunk.len - bs, bs)))
+ status = encryption->decrypt(encryption, iv);
+ if (status == SUCCESS)
{
- status = FAILED;
+ if (!keymat_v1->update_iv(keymat_v1, this->message_id,
+ chunk_create(chunk.ptr + chunk.len - bs, bs)))
+ {
+ status = FAILED;
+ }
}
}
+ else
+ {
+ status = FAILED;
+ }
}
else
{
- status = FAILED;
+ chunk.len -= encryption->get_length(encryption);
+ status = encryption->decrypt(encryption, chunk);
}
}
- else
- {
- chunk.len -= encryption->get_length(encryption);
- status = encryption->decrypt(encryption, chunk);
- }
if (status != SUCCESS)
{
return status;
@@ -1923,6 +2336,41 @@ static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
}
/**
+ * Decrypt an encrypted fragment payload.
+ */
+static status_t decrypt_fragment(private_message_t *this, keymat_t *keymat,
+ encrypted_fragment_payload_t *fragment)
+{
+ encrypted_payload_t *encrypted = (encrypted_payload_t*)fragment;
+ chunk_t chunk;
+ aead_t *aead;
+ size_t bs;
+
+ if (!keymat)
+ {
+ DBG1(DBG_ENC, "found encrypted fragment payload, but no keymat");
+ return INVALID_ARG;
+ }
+ aead = keymat->get_aead(keymat, TRUE);
+ if (!aead)
+ {
+ DBG1(DBG_ENC, "found encrypted fragment payload, but no transform set");
+ return INVALID_ARG;
+ }
+ bs = aead->get_block_size(aead);
+ encrypted->set_transform(encrypted, aead);
+ chunk = this->packet->get_data(this->packet);
+ if (chunk.len < encrypted->get_length(encrypted) ||
+ chunk.len < bs)
+ {
+ DBG1(DBG_ENC, "invalid payload length");
+ return VERIFY_ERROR;
+ }
+ chunk.len -= encrypted->get_length(encrypted);
+ return encrypted->decrypt(encrypted, chunk);
+}
+
+/**
* Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
* some SonicWall boxes?
*/
@@ -1941,7 +2389,7 @@ static bool accept_unencrypted_mm(private_message_t *this, payload_type_t type)
}
/**
- * Decrypt payload from the encryption payload
+ * Decrypt payload from the encrypted payload
*/
static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
{
@@ -1950,7 +2398,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
payload_rule_t *rule;
payload_type_t type;
status_t status = SUCCESS;
- bool was_encrypted = FALSE;
+ char *was_encrypted = NULL;
enumerator = this->payloads->create_enumerator(this->payloads);
while (enumerator->enumerate(enumerator, &payload))
@@ -1959,20 +2407,24 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
- if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
+ if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED ||
+ type == PLV2_FRAGMENT)
{
- encryption_payload_t *encryption;
-
if (was_encrypted)
{
- DBG1(DBG_ENC, "encrypted payload can't contain other payloads "
- "of type %N", payload_type_names, type);
+ DBG1(DBG_ENC, "%s can't contain other payloads of type %N",
+ was_encrypted, payload_type_names, type);
status = VERIFY_ERROR;
break;
}
+ }
+
+ if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
+ {
+ encrypted_payload_t *encryption;
DBG2(DBG_ENC, "found an encrypted payload");
- encryption = (encryption_payload_t*)payload;
+ encryption = (encrypted_payload_t*)payload;
this->payloads->remove_at(this->payloads, enumerator);
if (enumerator->enumerate(enumerator, NULL))
@@ -1988,7 +2440,27 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
{
break;
}
- was_encrypted = TRUE;
+ was_encrypted = "encrypted payload";
+ }
+ else if (type == PLV2_FRAGMENT)
+ {
+ encrypted_fragment_payload_t *fragment;
+
+ DBG2(DBG_ENC, "found an encrypted fragment payload");
+ fragment = (encrypted_fragment_payload_t*)payload;
+
+ if (enumerator->enumerate(enumerator, NULL))
+ {
+ DBG1(DBG_ENC, "encrypted fragment payload is not last payload");
+ status = VERIFY_ERROR;
+ break;
+ }
+ status = decrypt_fragment(this, keymat, fragment);
+ if (status != SUCCESS)
+ {
+ break;
+ }
+ was_encrypted = "encrypted fragment payload";
}
if (payload_is_known(type) && !was_encrypted &&
@@ -2085,10 +2557,15 @@ METHOD(message_t, parse_body, status_t,
return NOT_SUPPORTED;
}
- status = parse_payloads(this);
- if (status != SUCCESS)
- { /* error is already logged */
- return status;
+ /* reassembled IKEv2 messages are already parsed (except for the payloads
+ * contained in the encrypted payload, which are handled below) */
+ if (this->parser)
+ {
+ status = parse_payloads(this);
+ if (status != SUCCESS)
+ { /* error is already logged */
+ return status;
+ }
}
status = decrypt_payloads(this, keymat);
@@ -2142,7 +2619,7 @@ METHOD(message_t, parse_body, status_t,
}
chunk_free(&hash);
}
- if (this->is_encrypted)
+ if (this->is_encrypted && this->exchange_type != INFORMATIONAL_V1)
{ /* message verified, confirm IV */
if (!keymat_v1->confirm_iv(keymat_v1, this->message_id))
{
@@ -2153,13 +2630,234 @@ METHOD(message_t, parse_body, status_t,
return SUCCESS;
}
+/**
+ * Store the fragment data for the fragment with the given fragment number.
+ */
+static status_t add_fragment(private_message_t *this, u_int16_t num,
+ chunk_t data)
+{
+ fragment_t *fragment;
+ int i, insert_at = -1;
+
+ for (i = 0; i < array_count(this->fragments); i++)
+ {
+ array_get(this->fragments, i, &fragment);
+ if (fragment->num == num)
+ {
+ /* ignore a duplicate fragment */
+ DBG1(DBG_ENC, "received duplicate fragment #%hu", num);
+ return NEED_MORE;
+ }
+ if (fragment->num > num)
+ {
+ insert_at = i;
+ break;
+ }
+ }
+ this->frag->len += data.len;
+ if (this->frag->len > this->frag->max_packet)
+ {
+ DBG1(DBG_ENC, "fragmented IKE message is too large");
+ reset_defrag(this);
+ return FAILED;
+ }
+ INIT(fragment,
+ .num = num,
+ .data = chunk_clone(data),
+ );
+ array_insert(this->fragments, insert_at, fragment);
+ return SUCCESS;
+}
+
+/**
+ * Merge the cached fragment data and resets the defragmentation state.
+ * Also updates the IP addresses to those of the last received fragment.
+ */
+static chunk_t merge_fragments(private_message_t *this, message_t *last)
+{
+ fragment_t *fragment;
+ bio_writer_t *writer;
+ host_t *src, *dst;
+ chunk_t data;
+ int i;
+
+ writer = bio_writer_create(this->frag->len);
+ for (i = 0; i < array_count(this->fragments); i++)
+ {
+ array_get(this->fragments, i, &fragment);
+ writer->write_data(writer, fragment->data);
+ }
+ data = writer->extract_buf(writer);
+ writer->destroy(writer);
+
+ /* set addresses to those of the last fragment we received */
+ src = last->get_source(last);
+ dst = last->get_destination(last);
+ this->packet->set_source(this->packet, src->clone(src));
+ this->packet->set_destination(this->packet, dst->clone(dst));
+
+ reset_defrag(this);
+ free(this->frag);
+ this->frag = NULL;
+ return data;
+}
+
+METHOD(message_t, add_fragment_v1, status_t,
+ private_message_t *this, message_t *message)
+{
+ fragment_payload_t *payload;
+ chunk_t data;
+ u_int8_t num;
+ status_t status;
+
+ if (!this->frag)
+ {
+ return INVALID_STATE;
+ }
+ payload = (fragment_payload_t*)message->get_payload(message, PLV1_FRAGMENT);
+ if (!payload)
+ {
+ return INVALID_ARG;
+ }
+ if (!this->fragments || this->message_id != payload->get_id(payload))
+ {
+ reset_defrag(this);
+ this->message_id = payload->get_id(payload);
+ /* we don't know the total number of fragments, assume something */
+ this->fragments = array_create(0, 4);
+ }
+
+ num = payload->get_number(payload);
+ data = payload->get_data(payload);
+ if (!this->frag->last && payload->is_last(payload))
+ {
+ this->frag->last = num;
+ }
+ status = add_fragment(this, num, data);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ if (array_count(this->fragments) != this->frag->last)
+ {
+ /* there are some fragments missing */
+ DBG1(DBG_ENC, "received fragment #%hhu, waiting for complete IKE "
+ "message", num);
+ return NEED_MORE;
+ }
+
+ DBG1(DBG_ENC, "received fragment #%hhu, reassembling fragmented IKE "
+ "message", num);
+
+ data = merge_fragments(this, message);
+ this->packet->set_data(this->packet, data);
+ this->parser = parser_create(data);
+
+ if (parse_header(this) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "failed to parse header of reassembled IKE message");
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
+METHOD(message_t, add_fragment_v2, status_t,
+ private_message_t *this, message_t *message)
+{
+ encrypted_fragment_payload_t *encrypted_fragment;
+ encrypted_payload_t *encrypted;
+ payload_t *payload;
+ enumerator_t *enumerator;
+ chunk_t data;
+ u_int16_t total, num;
+ status_t status;
+
+ if (!this->frag)
+ {
+ return INVALID_STATE;
+ }
+ payload = message->get_payload(message, PLV2_FRAGMENT);
+ if (!payload || this->message_id != message->get_message_id(message))
+ {
+ return INVALID_ARG;
+ }
+ encrypted_fragment = (encrypted_fragment_payload_t*)payload;
+ total = encrypted_fragment->get_total_fragments(encrypted_fragment);
+ if (total > MAX_FRAGMENTS)
+ {
+ DBG1(DBG_IKE, "maximum fragment count exceeded");
+ reset_defrag(this);
+ return FAILED;
+ }
+ if (!this->fragments || total > this->frag->last)
+ {
+ reset_defrag(this);
+ this->frag->last = total;
+ this->fragments = array_create(0, total);
+ }
+ num = encrypted_fragment->get_fragment_number(encrypted_fragment);
+ data = encrypted_fragment->get_content(encrypted_fragment);
+ status = add_fragment(this, num, data);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+
+ if (num == 1)
+ {
+ /* the first fragment denotes the payload type of the first payload in
+ * the original encrypted payload, cache that */
+ this->first_payload = payload->get_next_type(payload);
+ /* move all unencrypted payloads contained in the first fragment */
+ enumerator = message->create_payload_enumerator(message);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ if (payload->get_type(payload) != PLV2_FRAGMENT)
+ {
+ message->remove_payload_at(message, enumerator);
+ this->payloads->insert_last(this->payloads, payload);
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ if (array_count(this->fragments) != total)
+ {
+ /* there are some fragments missing */
+ DBG1(DBG_ENC, "received fragment #%hu of %hu, waiting for complete IKE "
+ "message", num, total);
+ return NEED_MORE;
+ }
+
+ DBG1(DBG_ENC, "received fragment #%hu of %hu, reassembling fragmented IKE "
+ "message", num, total);
+
+ data = merge_fragments(this, message);
+ encrypted = encrypted_payload_create_from_plain(this->first_payload, data);
+ this->payloads->insert_last(this->payloads, encrypted);
+ /* update next payload type (could be an unencrypted payload) */
+ this->payloads->get_first(this->payloads, (void**)&payload);
+ this->first_payload = payload->get_type(payload);
+ return SUCCESS;
+}
+
METHOD(message_t, destroy, void,
private_message_t *this)
{
DESTROY_IF(this->ike_sa_id);
+ DESTROY_IF(this->parser);
this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
this->packet->destroy(this->packet);
- this->parser->destroy(this->parser);
+ if (this->frag)
+ {
+ reset_defrag(this);
+ free(this->frag);
+ }
+ else
+ {
+ array_destroy_offset(this->fragments, offsetof(packet_t, destroy));
+ }
free(this);
}
@@ -2195,6 +2893,9 @@ message_t *message_create_from_packet(packet_t *packet)
.disable_sort = _disable_sort,
.generate = _generate,
.is_encoded = _is_encoded,
+ .is_fragmented = _is_fragmented,
+ .fragment = _fragment,
+ .add_fragment = _add_fragment_v2,
.set_source = _set_source,
.get_source = _get_source,
.set_destination = _set_destination,
@@ -2207,6 +2908,7 @@ message_t *message_create_from_packet(packet_t *packet)
.parse_body = _parse_body,
.get_packet = _get_packet,
.get_packet_data = _get_packet_data,
+ .get_fragments = _get_fragments,
.destroy = _destroy,
},
.exchange_type = EXCHANGE_TYPE_UNDEFINED,
@@ -2232,3 +2934,34 @@ message_t *message_create(int major, int minor)
return this;
}
+
+/*
+ * Described in header.
+ */
+message_t *message_create_defrag(message_t *fragment)
+{
+ private_message_t *this;
+
+ if (!fragment->get_payload(fragment, PLV1_FRAGMENT) &&
+ !fragment->get_payload(fragment, PLV2_FRAGMENT))
+ {
+ return NULL;
+ }
+ this = (private_message_t*)clone_message((private_message_t*)fragment);
+ /* we don't need a parser for IKEv2, the one for IKEv1 is created after
+ * reassembling the original message */
+ this->parser->destroy(this->parser);
+ this->parser = NULL;
+ if (fragment->get_major_version(fragment) == IKEV1_MAJOR_VERSION)
+ {
+ /* we store the fragment ID in the message ID field, which should be
+ * zero for fragments, but make sure */
+ this->message_id = 0;
+ this->public.add_fragment = _add_fragment_v1;
+ }
+ INIT(this->frag,
+ .max_packet = lib->settings->get_int(lib->settings,
+ "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
+ );
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/message.h b/src/libcharon/encoding/message.h
index 7631a7c3a..a03aa8e96 100644
--- a/src/libcharon/encoding/message.h
+++ b/src/libcharon/encoding/message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -39,7 +39,7 @@ typedef struct message_t message_t;
*
* The message handles parsing and generation of payloads
* via parser_t/generator_t. Encryption is done transparently
- * via the encryption_payload_t. A set of rules for messages
+ * via the encrypted_payload_t. A set of rules for messages
* and payloads does check parsed messages.
*/
struct message_t {
@@ -265,6 +265,53 @@ struct message_t {
bool (*is_encoded)(message_t *this);
/**
+ * Generates the message split into fragments of the given size (total IP
+ * datagram length).
+ *
+ * @param keymat keymat to encrypt/sign message(s)
+ * @param frag_len fragment length (maximum total IP datagram length), 0
+ * for default value depending on address family
+ * @param fragments receives an enumerator with generated packet_t*,
+ * which are owned by the enumerator
+ * @return
+ * - SUCCESS if message could be fragmented
+ * - FAILED if fragmentation failed
+ * - and the possible return values of generate()
+ */
+ status_t (*fragment)(message_t *this, keymat_t *keymat, size_t frag_len,
+ enumerator_t **fragments);
+
+ /**
+ * Check if the message has been encoded and fragmented using fragment(),
+ * and whether there actually resulted fragments (if not is_encoded() will
+ * be TRUE).
+ *
+ * The packets of individual fragments can be retrieved with
+ * get_fragments().
+ *
+ * @return TRUE if message has been encoded and fragmented
+ */
+ bool (*is_fragmented)(message_t *this);
+
+ /**
+ * Add a fragment to the message if it was created with
+ * message_create_defrag().
+ *
+ * Once the message is completed it should be processed like any other
+ * inbound message.
+ *
+ * @param fragment fragment to add
+ * @return
+ * - SUCCESS if message was reassembled
+ * - NEED_MORE if not all fragments have yet been received
+ * - FAILED if reassembling failed
+ * - INVALID_ARG if fragment is invalid for some reason
+ * - INVALID_STATE if message was not created using
+ * message_create_defrag()
+ */
+ status_t (*add_fragment)(message_t *this, message_t *fragment);
+
+ /**
* Gets the source host informations.
*
* @warning Returned host_t object is not getting cloned,
@@ -337,11 +384,11 @@ struct message_t {
notify_payload_t* (*get_notify)(message_t *this, notify_type_t type);
/**
- * Returns a clone of the internal stored packet_t object.
+ * Returns a clone of the internally stored packet_t object.
*
* @return packet_t object as clone of internal one
*/
- packet_t * (*get_packet) (message_t *this);
+ packet_t *(*get_packet) (message_t *this);
/**
* Returns a chunk pointing to internal packet_t data.
@@ -351,6 +398,13 @@ struct message_t {
chunk_t (*get_packet_data) (message_t *this);
/**
+ * Returns internally stored packet_t* objects for each fragment.
+ *
+ * @return enumerator internal packet_t* objects
+ */
+ enumerator_t *(*get_fragments)(message_t *this);
+
+ /**
* Destroys a message and all including objects.
*/
void (*destroy) (message_t *this);
@@ -380,4 +434,14 @@ message_t *message_create_from_packet(packet_t *packet);
*/
message_t *message_create(int major, int minor);
+/**
+ * Creates a message_t object that is used to reassemble fragmented messages.
+ *
+ * Use add_fragment() to add fragments.
+ *
+ * @param fragment initial fragment (is not added)
+ * @return message_t object, NULL if fragment is not actually one
+ */
+message_t *message_create_defrag(message_t *fragment);
+
#endif /** MESSAGE_H_ @}*/
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index c33e30dd3..d6240fde2 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -32,7 +32,7 @@
#include <encoding/payloads/nonce_payload.h>
#include <encoding/payloads/id_payload.h>
#include <encoding/payloads/notify_payload.h>
-#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/encrypted_payload.h>
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/certreq_payload.h>
diff --git a/src/libcharon/encoding/payloads/encrypted_fragment_payload.h b/src/libcharon/encoding/payloads/encrypted_fragment_payload.h
new file mode 100644
index 000000000..1c2cc379f
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encrypted_fragment_payload.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup encrypted_fragment_payload encrypted_fragment_payload
+ * @{ @ingroup payloads
+ */
+
+#ifndef ENCRYPTED_FRAGMENT_PAYLOAD_H_
+#define ENCRYPTED_FRAGMENT_PAYLOAD_H_
+
+typedef struct encrypted_fragment_payload_t encrypted_fragment_payload_t;
+
+#include <encoding/payloads/encrypted_payload.h>
+
+/**
+ * The Encrypted Fragment Payload as described in RFC 7383
+ *
+ * The implementation is located in encrypted_payload.c as it is very similar.
+ */
+struct encrypted_fragment_payload_t {
+
+ /**
+ * Implements payload_t interface.
+ */
+ encrypted_payload_t encrypted;
+
+ /**
+ * Get the fragment number.
+ *
+ * @return fragment number
+ */
+ u_int16_t (*get_fragment_number)(encrypted_fragment_payload_t *this);
+
+ /**
+ * Get the total number of fragments.
+ *
+ * @return total number of fragments
+ */
+ u_int16_t (*get_total_fragments)(encrypted_fragment_payload_t *this);
+
+ /**
+ * Get the (decrypted) content of this payload.
+ *
+ * @return internal payload data
+ */
+ chunk_t (*get_content)(encrypted_fragment_payload_t *this);
+
+ /**
+ * Destroys an encrypted_fragment_payload_t object.
+ */
+ void (*destroy)(encrypted_fragment_payload_t *this);
+};
+
+/**
+ * Creates an empty encrypted_fragment_payload_t object.
+ *
+ * @return encrypted_fragment_payload_t object
+ */
+encrypted_fragment_payload_t *encrypted_fragment_payload_create();
+
+/**
+ * Creates an encrypted fragment payload from the given data.
+ *
+ * @param num fragment number (first one should be 1)
+ * @param total total number of fragments
+ * @param data fragment data (gets cloned)
+ * @return encrypted_fragment_payload_t object
+ */
+encrypted_fragment_payload_t *encrypted_fragment_payload_create_from_data(
+ u_int16_t num, u_int16_t total, chunk_t data);
+
+#endif /** ENCRYPTED_FRAGMENT_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encrypted_payload.c b/src/libcharon/encoding/payloads/encrypted_payload.c
new file mode 100644
index 000000000..5c574c34d
--- /dev/null
+++ b/src/libcharon/encoding/payloads/encrypted_payload.c
@@ -0,0 +1,1022 @@
+/*
+ * Copyright (C) 2011-2014 Tobias Brunner
+ * Copyright (C) 2005-2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "encrypted_payload.h"
+#include "encrypted_fragment_payload.h"
+
+#include <daemon.h>
+#include <encoding/payloads/encodings.h>
+#include <collections/linked_list.h>
+#include <encoding/parser.h>
+
+typedef struct private_encrypted_payload_t private_encrypted_payload_t;
+typedef struct private_encrypted_fragment_payload_t private_encrypted_fragment_payload_t;
+
+struct private_encrypted_payload_t {
+
+ /**
+ * Public encrypted_payload_t interface.
+ */
+ encrypted_payload_t public;
+
+ /**
+ * There is no next payload for an encrypted payload,
+ * since encrypted payload MUST be the last one.
+ * next_payload means here the first payload of the
+ * contained, encrypted payload.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Flags, including reserved bits
+ */
+ u_int8_t flags;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Chunk containing the IV, plain, padding and ICV.
+ */
+ chunk_t encrypted;
+
+ /**
+ * AEAD transform to use
+ */
+ aead_t *aead;
+
+ /**
+ * Contained payloads
+ */
+ linked_list_t *payloads;
+
+ /**
+ * Type of payload, PLV2_ENCRYPTED or PLV1_ENCRYPTED
+ */
+ payload_type_t type;
+};
+
+struct private_encrypted_fragment_payload_t {
+
+ /**
+ * Public interface.
+ */
+ encrypted_fragment_payload_t public;
+
+ /**
+ * The first fragment contains the type of the first payload contained in
+ * the original encrypted payload, for all other fragments it MUST be set
+ * to zero.
+ */
+ u_int8_t next_payload;
+
+ /**
+ * Flags, including reserved bits
+ */
+ u_int8_t flags;
+
+ /**
+ * Length of this payload
+ */
+ u_int16_t payload_length;
+
+ /**
+ * Chunk containing the IV, plain, padding and ICV.
+ */
+ chunk_t encrypted;
+
+ /**
+ * Fragment number
+ */
+ u_int16_t fragment_number;
+
+ /**
+ * Total fragments
+ */
+ u_int16_t total_fragments;
+
+ /**
+ * AEAD transform to use
+ */
+ aead_t *aead;
+
+ /**
+ * Chunk containing the plain packet data.
+ */
+ chunk_t plain;
+};
+
+/**
+ * Encoding rules to parse or generate a IKEv2-Encrypted Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encrypted_payload_t.
+ */
+static encoding_rule_t encodings_v2[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_encrypted_payload_t, next_payload) },
+ /* Critical and 7 reserved bits, all stored for reconstruction */
+ { U_INT_8, offsetof(private_encrypted_payload_t, flags) },
+ /* Length of the whole encrypted payload*/
+ { PAYLOAD_LENGTH, offsetof(private_encrypted_payload_t, payload_length) },
+ /* encrypted data, stored in a chunk. contains iv, data, padding */
+ { CHUNK_DATA, offsetof(private_encrypted_payload_t, encrypted) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Initialization Vector !
+ ! (length is block size for encryption algorithm) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
+ ! ! Pad Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ Integrity Checksum Data ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Encoding rules to parse or generate a complete encrypted IKEv1 message.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encrypted_payload_t.
+ */
+static encoding_rule_t encodings_v1[] = {
+ /* encrypted data, stored in a chunk */
+ { ENCRYPTED_DATA, offsetof(private_encrypted_payload_t, encrypted) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/**
+ * Encoding rules to parse or generate an IKEv2-Encrypted Fragment Payload.
+ *
+ * The defined offsets are the positions in a object of type
+ * private_encrypted_payload_t.
+ */
+static encoding_rule_t encodings_fragment[] = {
+ /* 1 Byte next payload type, stored in the field next_payload */
+ { U_INT_8, offsetof(private_encrypted_fragment_payload_t, next_payload) },
+ /* Critical and 7 reserved bits, all stored for reconstruction */
+ { U_INT_8, offsetof(private_encrypted_fragment_payload_t, flags) },
+ /* Length of the whole encryption payload*/
+ { PAYLOAD_LENGTH, offsetof(private_encrypted_fragment_payload_t, payload_length) },
+ /* Fragment number */
+ { U_INT_16, offsetof(private_encrypted_fragment_payload_t, fragment_number) },
+ /* Total number of fragments */
+ { U_INT_16, offsetof(private_encrypted_fragment_payload_t, total_fragments) },
+ /* encrypted data, stored in a chunk. contains iv, data, padding */
+ { CHUNK_DATA, offsetof(private_encrypted_fragment_payload_t, encrypted) },
+};
+
+/*
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Next Payload !C! RESERVED ! Payload Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Fragment Number | Total Fragments !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Initialization Vector !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! Encrypted IKE Payloads !
+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ! ! Padding (0-255 octets) !
+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
+ ! ! Pad Length !
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ~ Integrity Checksum Data ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+METHOD(payload_t, verify, status_t,
+ private_encrypted_payload_t *this)
+{
+ return SUCCESS;
+}
+
+METHOD(payload_t, get_encoding_rules, int,
+ private_encrypted_payload_t *this, encoding_rule_t **rules)
+{
+ if (this->type == PLV2_ENCRYPTED)
+ {
+ *rules = encodings_v2;
+ return countof(encodings_v2);
+ }
+ *rules = encodings_v1;
+ return countof(encodings_v1);
+}
+
+METHOD(payload_t, get_header_length, int,
+ private_encrypted_payload_t *this)
+{
+ if (this->type == PLV2_ENCRYPTED)
+ {
+ return 4;
+ }
+ return 0;
+}
+
+METHOD(payload_t, get_type, payload_type_t,
+ private_encrypted_payload_t *this)
+{
+ return this->type;
+}
+
+METHOD(payload_t, get_next_type, payload_type_t,
+ private_encrypted_payload_t *this)
+{
+ return this->next_payload;
+}
+
+METHOD(payload_t, set_next_type, void,
+ private_encrypted_payload_t *this, payload_type_t type)
+{
+ /* the next payload is set during add, still allow this for IKEv1 */
+ this->next_payload = type;
+}
+
+/**
+ * Get length of encryption/integrity overhead for the given plaintext length
+ */
+static size_t compute_overhead(aead_t *aead, size_t len)
+{
+ size_t bs, overhead;
+
+ /* padding */
+ bs = aead->get_block_size(aead);
+ overhead = bs - (len % bs);
+ /* add iv */
+ overhead += aead->get_iv_size(aead);
+ /* add icv */
+ overhead += aead->get_icv_size(aead);
+ return overhead;
+}
+
+/**
+ * Compute the length of the whole payload
+ */
+static void compute_length(private_encrypted_payload_t *this)
+{
+ enumerator_t *enumerator;
+ payload_t *payload;
+ size_t length = 0;
+
+ if (this->encrypted.len)
+ {
+ length = this->encrypted.len;
+ }
+ else
+ {
+ enumerator = this->payloads->create_enumerator(this->payloads);
+ while (enumerator->enumerate(enumerator, &payload))
+ {
+ length += payload->get_length(payload);
+ }
+ enumerator->destroy(enumerator);
+
+ if (this->aead)
+ {
+ length += compute_overhead(this->aead, length);
+ }
+ }
+ length += get_header_length(this);
+ this->payload_length = length;
+}
+
+METHOD2(payload_t, encrypted_payload_t, get_length, size_t,
+ private_encrypted_payload_t *this)
+{
+ compute_length(this);
+ return this->payload_length;
+}
+
+METHOD(encrypted_payload_t, add_payload, void,
+ private_encrypted_payload_t *this, payload_t *payload)
+{
+ payload_t *last_payload;
+
+ if (this->payloads->get_count(this->payloads) > 0)
+ {
+ this->payloads->get_last(this->payloads, (void **)&last_payload);
+ last_payload->set_next_type(last_payload, payload->get_type(payload));
+ }
+ else
+ {
+ this->next_payload = payload->get_type(payload);
+ }
+ payload->set_next_type(payload, PL_NONE);
+ this->payloads->insert_last(this->payloads, payload);
+ compute_length(this);
+}
+
+METHOD(encrypted_payload_t, remove_payload, payload_t *,
+ private_encrypted_payload_t *this)
+{
+ payload_t *payload;
+
+ if (this->payloads->remove_first(this->payloads,
+ (void**)&payload) == SUCCESS)
+ {
+ return payload;
+ }
+ return NULL;
+}
+
+/**
+ * Generate payload before encryption
+ */
+static chunk_t generate(private_encrypted_payload_t *this,
+ generator_t *generator)
+{
+ payload_t *current, *next;
+ enumerator_t *enumerator;
+ u_int32_t *lenpos;
+ chunk_t chunk = chunk_empty;
+
+ enumerator = this->payloads->create_enumerator(this->payloads);
+ if (enumerator->enumerate(enumerator, &current))
+ {
+ this->next_payload = current->get_type(current);
+
+ while (enumerator->enumerate(enumerator, &next))
+ {
+ current->set_next_type(current, next->get_type(next));
+ generator->generate_payload(generator, current);
+ current = next;
+ }
+ current->set_next_type(current, PL_NONE);
+ generator->generate_payload(generator, current);
+
+ chunk = generator->get_chunk(generator, &lenpos);
+ DBG2(DBG_ENC, "generated content in encrypted payload");
+ }
+ enumerator->destroy(enumerator);
+ return chunk;
+}
+
+METHOD(encrypted_payload_t, generate_payloads, void,
+ private_encrypted_payload_t *this, generator_t *generator)
+{
+ generate(this, generator);
+}
+
+/**
+ * Append the encrypted payload header to the associated data
+ */
+static chunk_t append_header(private_encrypted_payload_t *this, chunk_t assoc)
+{
+ struct {
+ u_int8_t next_payload;
+ u_int8_t flags;
+ u_int16_t length;
+ } __attribute__((packed)) header = {
+ .next_payload = this->next_payload,
+ .flags = this->flags,
+ .length = htons(get_length(this)),
+ };
+ return chunk_cat("cc", assoc, chunk_from_thing(header));
+}
+
+/**
+ * Encrypts the data in plain and returns it in an allocated chunk.
+ */
+static status_t encrypt_content(char *label, aead_t *aead, u_int64_t mid,
+ chunk_t plain, chunk_t assoc, chunk_t *encrypted)
+{
+ chunk_t iv, padding, icv, crypt;
+ iv_gen_t *iv_gen;
+ rng_t *rng;
+ size_t bs;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng)
+ {
+ DBG1(DBG_ENC, "encrypting %s failed, no RNG found", label);
+ return NOT_SUPPORTED;
+ }
+
+ iv_gen = aead->get_iv_gen(aead);
+ if (!iv_gen)
+ {
+ DBG1(DBG_ENC, "encrypting %s failed, no IV generator", label);
+ return NOT_SUPPORTED;
+ }
+
+ bs = aead->get_block_size(aead);
+ /* we need at least one byte padding to store the padding length */
+ padding.len = bs - (plain.len % bs);
+ iv.len = aead->get_iv_size(aead);
+ icv.len = aead->get_icv_size(aead);
+
+ /* prepare data to authenticate-encrypt:
+ * | IV | plain | padding | ICV |
+ * \____crypt______/ ^
+ * | /
+ * v /
+ * assoc -> + ------->/
+ */
+ *encrypted = chunk_alloc(iv.len + plain.len + padding.len + icv.len);
+ iv.ptr = encrypted->ptr;
+ memcpy(iv.ptr + iv.len, plain.ptr, plain.len);
+ plain.ptr = iv.ptr + iv.len;
+ padding.ptr = plain.ptr + plain.len;
+ icv.ptr = padding.ptr + padding.len;
+ crypt = chunk_create(plain.ptr, plain.len + padding.len);
+
+ if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) ||
+ !rng->get_bytes(rng, padding.len - 1, padding.ptr))
+ {
+ DBG1(DBG_ENC, "encrypting %s failed, no IV or padding", label);
+ rng->destroy(rng);
+
+ return FAILED;
+ }
+ padding.ptr[padding.len - 1] = padding.len - 1;
+ rng->destroy(rng);
+
+ DBG3(DBG_ENC, "%s encryption:", label);
+ DBG3(DBG_ENC, "IV %B", &iv);
+ DBG3(DBG_ENC, "plain %B", &plain);
+ DBG3(DBG_ENC, "padding %B", &padding);
+ DBG3(DBG_ENC, "assoc %B", &assoc);
+
+ if (!aead->encrypt(aead, crypt, assoc, iv, NULL))
+ {
+ return FAILED;
+ }
+ DBG3(DBG_ENC, "encrypted %B", &crypt);
+ DBG3(DBG_ENC, "ICV %B", &icv);
+ return SUCCESS;
+}
+
+METHOD(encrypted_payload_t, encrypt, status_t,
+ private_encrypted_payload_t *this, u_int64_t mid, chunk_t assoc)
+{
+ generator_t *generator;
+ chunk_t plain;
+ status_t status;
+
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "encrypting encrypted payload failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ free(this->encrypted.ptr);
+ generator = generator_create();
+ plain = generate(this, generator);
+ assoc = append_header(this, assoc);
+ status = encrypt_content("encrypted payload", this->aead, mid, plain, assoc,
+ &this->encrypted);
+ generator->destroy(generator);
+ free(assoc.ptr);
+ return status;
+}
+
+METHOD(encrypted_payload_t, encrypt_v1, status_t,
+ private_encrypted_payload_t *this, u_int64_t mid, chunk_t iv)
+{
+ generator_t *generator;
+ chunk_t plain, padding;
+ size_t bs;
+
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "encryption failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ generator = generator_create();
+ plain = generate(this, generator);
+ bs = this->aead->get_block_size(this->aead);
+ padding.len = bs - (plain.len % bs);
+
+ /* prepare data to encrypt:
+ * | plain | padding | */
+ free(this->encrypted.ptr);
+ this->encrypted = chunk_alloc(plain.len + padding.len);
+ memcpy(this->encrypted.ptr, plain.ptr, plain.len);
+ plain.ptr = this->encrypted.ptr;
+ padding.ptr = plain.ptr + plain.len;
+ memset(padding.ptr, 0, padding.len);
+ generator->destroy(generator);
+
+ DBG3(DBG_ENC, "encrypting payloads:");
+ DBG3(DBG_ENC, "IV %B", &iv);
+ DBG3(DBG_ENC, "plain %B", &plain);
+ DBG3(DBG_ENC, "padding %B", &padding);
+
+ if (!this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
+ {
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
+
+ return SUCCESS;
+}
+
+/**
+ * Parse the payloads after decryption.
+ */
+static status_t parse(private_encrypted_payload_t *this, chunk_t plain)
+{
+ parser_t *parser;
+ payload_type_t type;
+
+ parser = parser_create(plain);
+ type = this->next_payload;
+ while (type != PL_NONE)
+ {
+ payload_t *payload;
+
+ if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
+ {
+ DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
+ payload_type_names, type);
+ parser->destroy(parser);
+ return PARSE_ERROR;
+ }
+ if (parser->parse_payload(parser, type, &payload) != SUCCESS)
+ {
+ parser->destroy(parser);
+ return PARSE_ERROR;
+ }
+ if (payload->verify(payload) != SUCCESS)
+ {
+ DBG1(DBG_ENC, "%N verification failed",
+ payload_type_names, payload->get_type(payload));
+ payload->destroy(payload);
+ parser->destroy(parser);
+ return VERIFY_ERROR;
+ }
+ type = payload->get_next_type(payload);
+ this->payloads->insert_last(this->payloads, payload);
+ }
+ parser->destroy(parser);
+ DBG2(DBG_ENC, "parsed content of encrypted payload");
+ return SUCCESS;
+}
+
+/**
+ * Decrypts the given data in-place and returns a chunk pointing to the
+ * resulting plaintext.
+ */
+static status_t decrypt_content(char *label, aead_t *aead, chunk_t encrypted,
+ chunk_t assoc, chunk_t *plain)
+{
+ chunk_t iv, padding, icv, crypt;
+ size_t bs;
+
+ /* prepare data to authenticate-decrypt:
+ * | IV | plain | padding | ICV |
+ * \____crypt______/ ^
+ * | /
+ * v /
+ * assoc -> + ------->/
+ */
+ bs = aead->get_block_size(aead);
+ iv.len = aead->get_iv_size(aead);
+ iv.ptr = encrypted.ptr;
+ icv.len = aead->get_icv_size(aead);
+ icv.ptr = encrypted.ptr + encrypted.len - icv.len;
+ crypt.ptr = iv.ptr + iv.len;
+ crypt.len = encrypted.len - iv.len;
+
+ if (iv.len + icv.len > encrypted.len ||
+ (crypt.len - icv.len) % bs)
+ {
+ DBG1(DBG_ENC, "decrypting %s payload failed, invalid length", label);
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "%s decryption:", label);
+ DBG3(DBG_ENC, "IV %B", &iv);
+ DBG3(DBG_ENC, "encrypted %B", &crypt);
+ DBG3(DBG_ENC, "ICV %B", &icv);
+ DBG3(DBG_ENC, "assoc %B", &assoc);
+
+ if (!aead->decrypt(aead, crypt, assoc, iv, NULL))
+ {
+ DBG1(DBG_ENC, "verifying %s integrity failed", label);
+ return FAILED;
+ }
+
+ *plain = chunk_create(crypt.ptr, crypt.len - icv.len);
+ padding.len = plain->ptr[plain->len - 1] + 1;
+ if (padding.len > plain->len)
+ {
+ DBG1(DBG_ENC, "decrypting %s failed, padding invalid %B", label,
+ &crypt);
+ return PARSE_ERROR;
+ }
+ plain->len -= padding.len;
+ padding.ptr = plain->ptr + plain->len;
+
+ DBG3(DBG_ENC, "plain %B", plain);
+ DBG3(DBG_ENC, "padding %B", &padding);
+ return SUCCESS;
+}
+
+METHOD(encrypted_payload_t, decrypt, status_t,
+ private_encrypted_payload_t *this, chunk_t assoc)
+{
+ chunk_t plain;
+ status_t status;
+
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "decrypting encrypted payload failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ assoc = append_header(this, assoc);
+ status = decrypt_content("encrypted payload", this->aead, this->encrypted,
+ assoc, &plain);
+ free(assoc.ptr);
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ return parse(this, plain);
+}
+
+METHOD(encrypted_payload_t, decrypt_plain, status_t,
+ private_encrypted_payload_t *this, chunk_t assoc)
+{
+ if (!this->encrypted.ptr)
+ {
+ return FAILED;
+ }
+ return parse(this, this->encrypted);
+}
+
+METHOD(encrypted_payload_t, decrypt_v1, status_t,
+ private_encrypted_payload_t *this, chunk_t iv)
+{
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "decryption failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ /* data must be a multiple of block size */
+ if (iv.len != this->aead->get_block_size(this->aead) ||
+ this->encrypted.len < iv.len || this->encrypted.len % iv.len)
+ {
+ DBG1(DBG_ENC, "decryption failed, invalid length");
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "decrypting payloads:");
+ DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
+
+ if (!this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
+ {
+ return FAILED;
+ }
+
+ DBG3(DBG_ENC, "plain %B", &this->encrypted);
+
+ return parse(this, this->encrypted);
+}
+
+METHOD(encrypted_payload_t, set_transform, void,
+ private_encrypted_payload_t *this, aead_t* aead)
+{
+ this->aead = aead;
+}
+
+METHOD2(payload_t, encrypted_payload_t, destroy, void,
+ private_encrypted_payload_t *this)
+{
+ this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
+ free(this->encrypted.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+encrypted_payload_t *encrypted_payload_create(payload_type_t type)
+{
+ private_encrypted_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .payload_interface = {
+ .verify = _verify,
+ .get_encoding_rules = _get_encoding_rules,
+ .get_header_length = _get_header_length,
+ .get_length = _get_length,
+ .get_next_type = _get_next_type,
+ .set_next_type = _set_next_type,
+ .get_type = _get_type,
+ .destroy = _destroy,
+ },
+ .get_length = _get_length,
+ .add_payload = _add_payload,
+ .remove_payload = _remove_payload,
+ .generate_payloads = _generate_payloads,
+ .set_transform = _set_transform,
+ .encrypt = _encrypt,
+ .decrypt = _decrypt,
+ .destroy = _destroy,
+ },
+ .next_payload = PL_NONE,
+ .payloads = linked_list_create(),
+ .type = type,
+ );
+ this->payload_length = get_header_length(this);
+
+ if (type == PLV1_ENCRYPTED)
+ {
+ this->public.encrypt = _encrypt_v1;
+ this->public.decrypt = _decrypt_v1;
+ }
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+encrypted_payload_t *encrypted_payload_create_from_plain(payload_type_t next,
+ chunk_t plain)
+{
+ private_encrypted_payload_t *this;
+
+ this = (private_encrypted_payload_t*)encrypted_payload_create(PLV2_ENCRYPTED);
+ this->public.decrypt = _decrypt_plain;
+ this->next_payload = next;
+ this->encrypted = plain;
+ compute_length(this);
+
+ return &this->public;
+}
+
+METHOD(payload_t, frag_verify, status_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ if (!this->fragment_number || !this->total_fragments ||
+ this->fragment_number > this->total_fragments)
+ {
+ DBG1(DBG_ENC, "invalid fragment number (%u) or total fragments (%u)",
+ this->fragment_number, this->total_fragments);
+ return FAILED;
+ }
+ if (this->fragment_number > 1 && this->next_payload != 0)
+ {
+ DBG1(DBG_ENC, "invalid next payload (%u) for fragment %u, ignored",
+ this->next_payload, this->fragment_number);
+ this->next_payload = 0;
+ }
+ return SUCCESS;
+}
+
+METHOD(payload_t, frag_get_encoding_rules, int,
+ private_encrypted_fragment_payload_t *this, encoding_rule_t **rules)
+{
+ *rules = encodings_fragment;
+ return countof(encodings_fragment);
+}
+
+METHOD(payload_t, frag_get_header_length, int,
+ private_encrypted_fragment_payload_t *this)
+{
+ return 8;
+}
+
+METHOD(payload_t, frag_get_type, payload_type_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ return PLV2_FRAGMENT;
+}
+
+METHOD(payload_t, frag_get_next_type, payload_type_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ return this->next_payload;
+}
+
+METHOD(payload_t, frag_set_next_type, void,
+ private_encrypted_fragment_payload_t *this, payload_type_t type)
+{
+ if (this->fragment_number == 1 && this->next_payload == PL_NONE)
+ {
+ this->next_payload = type;
+ }
+}
+
+METHOD2(payload_t, encrypted_payload_t, frag_get_length, size_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ if (this->encrypted.len)
+ {
+ this->payload_length = this->encrypted.len;
+ }
+ else
+ {
+ this->payload_length = this->plain.len;
+
+ if (this->aead)
+ {
+ this->payload_length += compute_overhead(this->aead,
+ this->payload_length);
+ }
+ }
+ this->payload_length += frag_get_header_length(this);
+ return this->payload_length;
+}
+
+METHOD(encrypted_fragment_payload_t, get_fragment_number, u_int16_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ return this->fragment_number;
+}
+
+METHOD(encrypted_fragment_payload_t, get_total_fragments, u_int16_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ return this->total_fragments;
+}
+
+METHOD(encrypted_fragment_payload_t, frag_get_content, chunk_t,
+ private_encrypted_fragment_payload_t *this)
+{
+ return this->plain;
+}
+
+METHOD(encrypted_payload_t, frag_add_payload, void,
+ private_encrypted_fragment_payload_t *this, payload_t* payload)
+{
+ payload->destroy(payload);
+}
+
+METHOD(encrypted_payload_t, frag_set_transform, void,
+ private_encrypted_fragment_payload_t *this, aead_t* aead)
+{
+ this->aead = aead;
+}
+
+/**
+ * Append the encrypted fragment payload header to the associated data
+ */
+static chunk_t append_header_frag(private_encrypted_fragment_payload_t *this,
+ chunk_t assoc)
+{
+ struct {
+ u_int8_t next_payload;
+ u_int8_t flags;
+ u_int16_t length;
+ u_int16_t fragment_number;
+ u_int16_t total_fragments;
+ } __attribute__((packed)) header = {
+ .next_payload = this->next_payload,
+ .flags = this->flags,
+ .length = htons(frag_get_length(this)),
+ .fragment_number = htons(this->fragment_number),
+ .total_fragments = htons(this->total_fragments),
+ };
+ return chunk_cat("cc", assoc, chunk_from_thing(header));
+}
+
+METHOD(encrypted_payload_t, frag_encrypt, status_t,
+ private_encrypted_fragment_payload_t *this, u_int64_t mid, chunk_t assoc)
+{
+ status_t status;
+
+ if (!this->aead)
+ {
+ DBG1(DBG_ENC, "encrypting encrypted fragment payload failed, "
+ "transform missing");
+ return INVALID_STATE;
+ }
+ free(this->encrypted.ptr);
+ assoc = append_header_frag(this, assoc);
+ status = encrypt_content("encrypted fragment payload", this->aead, mid,
+ this->plain, assoc, &this->encrypted);
+ free(assoc.ptr);
+ return status;
+}
+
+METHOD(encrypted_payload_t, frag_decrypt, status_t,
+ private_encrypted_fragment_payload_t *this, chunk_t assoc)
+{
+ status_t status;
+
+ if (!this->aead)
+ {
+ DBG1(DBG_ENC, "decrypting encrypted fragment payload failed, "
+ "transform missing");
+ return INVALID_STATE;
+ }
+ free(this->plain.ptr);
+ assoc = append_header_frag(this, assoc);
+ status = decrypt_content("encrypted fragment payload", this->aead,
+ this->encrypted, assoc, &this->plain);
+ this->plain = chunk_clone(this->plain);
+ free(assoc.ptr);
+ return status;
+}
+
+METHOD2(payload_t, encrypted_payload_t, frag_destroy, void,
+ private_encrypted_fragment_payload_t *this)
+{
+ free(this->encrypted.ptr);
+ free(this->plain.ptr);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+encrypted_fragment_payload_t *encrypted_fragment_payload_create()
+{
+ private_encrypted_fragment_payload_t *this;
+
+ INIT(this,
+ .public = {
+ .encrypted = {
+ .payload_interface = {
+ .verify = _frag_verify,
+ .get_encoding_rules = _frag_get_encoding_rules,
+ .get_header_length = _frag_get_header_length,
+ .get_length = _frag_get_length,
+ .get_next_type = _frag_get_next_type,
+ .set_next_type = _frag_set_next_type,
+ .get_type = _frag_get_type,
+ .destroy = _frag_destroy,
+ },
+ .get_length = _frag_get_length,
+ .add_payload = _frag_add_payload,
+ .remove_payload = (void*)return_null,
+ .generate_payloads = nop,
+ .set_transform = _frag_set_transform,
+ .encrypt = _frag_encrypt,
+ .decrypt = _frag_decrypt,
+ .destroy = _frag_destroy,
+ },
+ .get_fragment_number = _get_fragment_number,
+ .get_total_fragments = _get_total_fragments,
+ .get_content = _frag_get_content,
+ },
+ .next_payload = PL_NONE,
+ );
+ this->payload_length = frag_get_header_length(this);
+
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+encrypted_fragment_payload_t *encrypted_fragment_payload_create_from_data(
+ u_int16_t num, u_int16_t total, chunk_t plain)
+{
+ private_encrypted_fragment_payload_t *this;
+
+ this = (private_encrypted_fragment_payload_t*)encrypted_fragment_payload_create();
+ this->fragment_number = num;
+ this->total_fragments = total;
+ this->plain = chunk_clone(plain);
+
+ return &this->public;
+}
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encrypted_payload.h
index ee44c2de1..be59e3c2d 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.h
+++ b/src/libcharon/encoding/payloads/encrypted_payload.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2014 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
* Copyright (C) 2005 Jan Hutter
@@ -16,23 +17,24 @@
*/
/**
- * @defgroup encryption_payload encryption_payload
+ * @defgroup encrypted_payload encrypted_payload
* @{ @ingroup payloads
*/
-#ifndef ENCRYPTION_PAYLOAD_H_
-#define ENCRYPTION_PAYLOAD_H_
+#ifndef ENCRYPTED_PAYLOAD_H_
+#define ENCRYPTED_PAYLOAD_H_
-typedef struct encryption_payload_t encryption_payload_t;
+typedef struct encrypted_payload_t encrypted_payload_t;
#include <library.h>
#include <crypto/aead.h>
#include <encoding/payloads/payload.h>
+#include <encoding/generator.h>
/**
- * The encryption payload as described in RFC section 3.14.
+ * The encrypted payload as described in RFC section 3.14.
*/
-struct encryption_payload_t {
+struct encrypted_payload_t {
/**
* Implements payload_t interface.
@@ -44,14 +46,14 @@ struct encryption_payload_t {
*
* @return (expected) payload length
*/
- size_t (*get_length)(encryption_payload_t *this);
+ size_t (*get_length)(encrypted_payload_t *this);
/**
* Adds a payload to this encryption payload.
*
* @param payload payload_t object to add
*/
- void (*add_payload) (encryption_payload_t *this, payload_t *payload);
+ void (*add_payload) (encrypted_payload_t *this, payload_t *payload);
/**
* Remove the first payload in the list
@@ -59,14 +61,22 @@ struct encryption_payload_t {
* @param payload removed payload
* @return payload, NULL if none left
*/
- payload_t* (*remove_payload)(encryption_payload_t *this);
+ payload_t* (*remove_payload)(encrypted_payload_t *this);
+
+ /**
+ * Uses the given generator to generate the contained payloads.
+ *
+ * @param generator generator used to generate the contained payloads
+ */
+ void (*generate_payloads)(encrypted_payload_t *this,
+ generator_t *generator);
/**
* Set the AEAD transform to use.
*
* @param aead aead transform to use
*/
- void (*set_transform) (encryption_payload_t *this, aead_t *aead);
+ void (*set_transform) (encrypted_payload_t *this, aead_t *aead);
/**
* Generate, encrypt and sign contained payloads.
@@ -78,7 +88,7 @@ struct encryption_payload_t {
* - FAILED if encryption failed
* - INVALID_STATE if aead not supplied, but needed
*/
- status_t (*encrypt) (encryption_payload_t *this, u_int64_t mid,
+ status_t (*encrypt) (encrypted_payload_t *this, u_int64_t mid,
chunk_t assoc);
/**
@@ -92,20 +102,31 @@ struct encryption_payload_t {
* - FAILED if integrity check failed
* - INVALID_STATE if aead not supplied, but needed
*/
- status_t (*decrypt) (encryption_payload_t *this, chunk_t assoc);
+ status_t (*decrypt) (encrypted_payload_t *this, chunk_t assoc);
/**
- * Destroys an encryption_payload_t object.
+ * Destroys an encrypted_payload_t object.
*/
- void (*destroy) (encryption_payload_t *this);
+ void (*destroy) (encrypted_payload_t *this);
};
/**
- * Creates an empty encryption_payload_t object.
+ * Creates an empty encrypted_payload_t object.
*
* @param type PLV2_ENCRYPTED or PLV1_ENCRYPTED
- * @return encryption_payload_t object
+ * @return encrypted_payload_t object
+ */
+encrypted_payload_t *encrypted_payload_create(payload_type_t type);
+
+/**
+ * Creates an encrypted payload with the given plain text data and next payload
+ * type.
+ *
+ * @param next next payload type
+ * @param plain plaintext data (gets adopted)
+ * @return encrypted_payload_t object
*/
-encryption_payload_t *encryption_payload_create(payload_type_t type);
+encrypted_payload_t *encrypted_payload_create_from_plain(payload_type_t next,
+ chunk_t plain);
-#endif /** ENCRYPTION_PAYLOAD_H_ @}*/
+#endif /** ENCRYPTED_PAYLOAD_H_ @}*/
diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
deleted file mode 100644
index 5784562f8..000000000
--- a/src/libcharon/encoding/payloads/encryption_payload.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright (C) 2005-2010 Martin Willi
- * Copyright (C) 2010 revosec AG
- * Copyright (C) 2011 Tobias Brunner
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stddef.h>
-#include <string.h>
-
-#include "encryption_payload.h"
-
-#include <daemon.h>
-#include <encoding/payloads/encodings.h>
-#include <collections/linked_list.h>
-#include <encoding/generator.h>
-#include <encoding/parser.h>
-
-typedef struct private_encryption_payload_t private_encryption_payload_t;
-
-/**
- * Private data of an encryption_payload_t' Object.
- *
- */
-struct private_encryption_payload_t {
-
- /**
- * Public encryption_payload_t interface.
- */
- encryption_payload_t public;
-
- /**
- * There is no next payload for an encryption payload,
- * since encryption payload MUST be the last one.
- * next_payload means here the first payload of the
- * contained, encrypted payload.
- */
- u_int8_t next_payload;
-
- /**
- * Flags, including reserved bits
- */
- u_int8_t flags;
-
- /**
- * Length of this payload
- */
- u_int16_t payload_length;
-
- /**
- * Chunk containing the IV, plain, padding and ICV.
- */
- chunk_t encrypted;
-
- /**
- * AEAD transform to use
- */
- aead_t *aead;
-
- /**
- * Contained payloads
- */
- linked_list_t *payloads;
-
- /**
- * Type of payload, PLV2_ENCRYPTED or PLV1_ENCRYPTED
- */
- payload_type_t type;
-};
-
-/**
- * Encoding rules to parse or generate a IKEv2-Encryption Payload.
- *
- * The defined offsets are the positions in a object of type
- * private_encryption_payload_t.
- */
-static encoding_rule_t encodings_v2[] = {
- /* 1 Byte next payload type, stored in the field next_payload */
- { U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
- /* Critical and 7 reserved bits, all stored for reconstruction */
- { U_INT_8, offsetof(private_encryption_payload_t, flags) },
- /* Length of the whole encryption payload*/
- { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
- /* encrypted data, stored in a chunk. contains iv, data, padding */
- { CHUNK_DATA, offsetof(private_encryption_payload_t, encrypted) },
-};
-
-/*
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Next Payload !C! RESERVED ! Payload Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Initialization Vector !
- ! (length is block size for encryption algorithm) !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Encrypted IKE Payloads !
- + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! ! Padding (0-255 octets) !
- +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
- ! ! Pad Length !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ~ Integrity Checksum Data ~
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
-
-/**
- * Encoding rules to parse or generate a complete encrypted IKEv1 message.
- *
- * The defined offsets are the positions in a object of type
- * private_encryption_payload_t.
- */
-static encoding_rule_t encodings_v1[] = {
- /* encrypted data, stored in a chunk */
- { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
-};
-
-/*
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! Encrypted IKE Payloads !
- + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! ! Padding (0-255 octets) !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-*/
-
-METHOD(payload_t, verify, status_t,
- private_encryption_payload_t *this)
-{
- return SUCCESS;
-}
-
-METHOD(payload_t, get_encoding_rules, int,
- private_encryption_payload_t *this, encoding_rule_t **rules)
-{
- if (this->type == PLV2_ENCRYPTED)
- {
- *rules = encodings_v2;
- return countof(encodings_v2);
- }
- *rules = encodings_v1;
- return countof(encodings_v1);
-}
-
-METHOD(payload_t, get_header_length, int,
- private_encryption_payload_t *this)
-{
- if (this->type == PLV2_ENCRYPTED)
- {
- return 4;
- }
- return 0;
-}
-
-METHOD(payload_t, get_type, payload_type_t,
- private_encryption_payload_t *this)
-{
- return this->type;
-}
-
-METHOD(payload_t, get_next_type, payload_type_t,
- private_encryption_payload_t *this)
-{
- return this->next_payload;
-}
-
-METHOD(payload_t, set_next_type, void,
- private_encryption_payload_t *this, payload_type_t type)
-{
- /* the next payload is set during add, still allow this for IKEv1 */
- this->next_payload = type;
-}
-
-/**
- * Compute the length of the whole payload
- */
-static void compute_length(private_encryption_payload_t *this)
-{
- enumerator_t *enumerator;
- payload_t *payload;
- size_t bs, length = 0;
-
- if (this->encrypted.len)
- {
- length = this->encrypted.len;
- }
- else
- {
- enumerator = this->payloads->create_enumerator(this->payloads);
- while (enumerator->enumerate(enumerator, &payload))
- {
- length += payload->get_length(payload);
- }
- enumerator->destroy(enumerator);
-
- if (this->aead)
- {
- /* append padding */
- bs = this->aead->get_block_size(this->aead);
- length += bs - (length % bs);
- /* add iv */
- length += this->aead->get_iv_size(this->aead);
- /* add icv */
- length += this->aead->get_icv_size(this->aead);
- }
- }
- length += get_header_length(this);
- this->payload_length = length;
-}
-
-METHOD2(payload_t, encryption_payload_t, get_length, size_t,
- private_encryption_payload_t *this)
-{
- compute_length(this);
- return this->payload_length;
-}
-
-METHOD(encryption_payload_t, add_payload, void,
- private_encryption_payload_t *this, payload_t *payload)
-{
- payload_t *last_payload;
-
- if (this->payloads->get_count(this->payloads) > 0)
- {
- this->payloads->get_last(this->payloads, (void **)&last_payload);
- last_payload->set_next_type(last_payload, payload->get_type(payload));
- }
- else
- {
- this->next_payload = payload->get_type(payload);
- }
- payload->set_next_type(payload, PL_NONE);
- this->payloads->insert_last(this->payloads, payload);
- compute_length(this);
-}
-
-METHOD(encryption_payload_t, remove_payload, payload_t *,
- private_encryption_payload_t *this)
-{
- payload_t *payload;
-
- if (this->payloads->remove_first(this->payloads,
- (void**)&payload) == SUCCESS)
- {
- return payload;
- }
- return NULL;
-}
-
-/**
- * Generate payload before encryption
- */
-static chunk_t generate(private_encryption_payload_t *this,
- generator_t *generator)
-{
- payload_t *current, *next;
- enumerator_t *enumerator;
- u_int32_t *lenpos;
- chunk_t chunk = chunk_empty;
-
- enumerator = this->payloads->create_enumerator(this->payloads);
- if (enumerator->enumerate(enumerator, &current))
- {
- this->next_payload = current->get_type(current);
-
- while (enumerator->enumerate(enumerator, &next))
- {
- current->set_next_type(current, next->get_type(next));
- generator->generate_payload(generator, current);
- current = next;
- }
- current->set_next_type(current, PL_NONE);
- generator->generate_payload(generator, current);
-
- chunk = generator->get_chunk(generator, &lenpos);
- DBG2(DBG_ENC, "generated content in encryption payload");
- }
- enumerator->destroy(enumerator);
- return chunk;
-}
-
-/**
- * Append the encryption payload header to the associated data
- */
-static chunk_t append_header(private_encryption_payload_t *this, chunk_t assoc)
-{
- struct {
- u_int8_t next_payload;
- u_int8_t flags;
- u_int16_t length;
- } __attribute__((packed)) header = {
- .next_payload = this->next_payload,
- .flags = this->flags,
- .length = htons(get_length(this)),
- };
- return chunk_cat("cc", assoc, chunk_from_thing(header));
-}
-
-METHOD(encryption_payload_t, encrypt, status_t,
- private_encryption_payload_t *this, u_int64_t mid, chunk_t assoc)
-{
- chunk_t iv, plain, padding, icv, crypt;
- generator_t *generator;
- iv_gen_t *iv_gen;
- rng_t *rng;
- size_t bs;
-
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "encrypting encryption payload failed, transform missing");
- return INVALID_STATE;
- }
-
- rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
- if (!rng)
- {
- DBG1(DBG_ENC, "encrypting encryption payload failed, no RNG found");
- return NOT_SUPPORTED;
- }
-
- iv_gen = this->aead->get_iv_gen(this->aead);
- if (!iv_gen)
- {
- DBG1(DBG_ENC, "encrypting encryption payload failed, no IV generator");
- return NOT_SUPPORTED;
- }
-
- assoc = append_header(this, assoc);
-
- generator = generator_create();
- plain = generate(this, generator);
- bs = this->aead->get_block_size(this->aead);
- /* we need at least one byte padding to store the padding length */
- padding.len = bs - (plain.len % bs);
- iv.len = this->aead->get_iv_size(this->aead);
- icv.len = this->aead->get_icv_size(this->aead);
-
- /* prepare data to authenticate-encrypt:
- * | IV | plain | padding | ICV |
- * \____crypt______/ ^
- * | /
- * v /
- * assoc -> + ------->/
- */
- free(this->encrypted.ptr);
- this->encrypted = chunk_alloc(iv.len + plain.len + padding.len + icv.len);
- iv.ptr = this->encrypted.ptr;
- memcpy(iv.ptr + iv.len, plain.ptr, plain.len);
- plain.ptr = iv.ptr + iv.len;
- padding.ptr = plain.ptr + plain.len;
- icv.ptr = padding.ptr + padding.len;
- crypt = chunk_create(plain.ptr, plain.len + padding.len);
- generator->destroy(generator);
-
- if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) ||
- !rng->get_bytes(rng, padding.len - 1, padding.ptr))
- {
- DBG1(DBG_ENC, "encrypting encryption payload failed, no IV or padding");
- rng->destroy(rng);
- free(assoc.ptr);
- return FAILED;
- }
- padding.ptr[padding.len - 1] = padding.len - 1;
- rng->destroy(rng);
-
- DBG3(DBG_ENC, "encryption payload encryption:");
- DBG3(DBG_ENC, "IV %B", &iv);
- DBG3(DBG_ENC, "plain %B", &plain);
- DBG3(DBG_ENC, "padding %B", &padding);
- DBG3(DBG_ENC, "assoc %B", &assoc);
-
- if (!this->aead->encrypt(this->aead, crypt, assoc, iv, NULL))
- {
- free(assoc.ptr);
- return FAILED;
- }
-
- DBG3(DBG_ENC, "encrypted %B", &crypt);
- DBG3(DBG_ENC, "ICV %B", &icv);
-
- free(assoc.ptr);
-
- return SUCCESS;
-}
-
-METHOD(encryption_payload_t, encrypt_v1, status_t,
- private_encryption_payload_t *this, u_int64_t mid, chunk_t iv)
-{
- generator_t *generator;
- chunk_t plain, padding;
- size_t bs;
-
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "encryption failed, transform missing");
- return INVALID_STATE;
- }
-
- generator = generator_create();
- plain = generate(this, generator);
- bs = this->aead->get_block_size(this->aead);
- padding.len = bs - (plain.len % bs);
-
- /* prepare data to encrypt:
- * | plain | padding | */
- free(this->encrypted.ptr);
- this->encrypted = chunk_alloc(plain.len + padding.len);
- memcpy(this->encrypted.ptr, plain.ptr, plain.len);
- plain.ptr = this->encrypted.ptr;
- padding.ptr = plain.ptr + plain.len;
- memset(padding.ptr, 0, padding.len);
- generator->destroy(generator);
-
- DBG3(DBG_ENC, "encrypting payloads:");
- DBG3(DBG_ENC, "plain %B", &plain);
- DBG3(DBG_ENC, "padding %B", &padding);
-
- if (!this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
- {
- return FAILED;
- }
-
- DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
-
- return SUCCESS;
-}
-
-/**
- * Parse the payloads after decryption.
- */
-static status_t parse(private_encryption_payload_t *this, chunk_t plain)
-{
- parser_t *parser;
- payload_type_t type;
-
- parser = parser_create(plain);
- type = this->next_payload;
- while (type != PL_NONE)
- {
- payload_t *payload;
-
- if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
- {
- DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
- payload_type_names, type);
- parser->destroy(parser);
- return PARSE_ERROR;
- }
- if (parser->parse_payload(parser, type, &payload) != SUCCESS)
- {
- parser->destroy(parser);
- return PARSE_ERROR;
- }
- if (payload->verify(payload) != SUCCESS)
- {
- DBG1(DBG_ENC, "%N verification failed",
- payload_type_names, payload->get_type(payload));
- payload->destroy(payload);
- parser->destroy(parser);
- return VERIFY_ERROR;
- }
- type = payload->get_next_type(payload);
- this->payloads->insert_last(this->payloads, payload);
- }
- parser->destroy(parser);
- DBG2(DBG_ENC, "parsed content of encryption payload");
- return SUCCESS;
-}
-
-METHOD(encryption_payload_t, decrypt, status_t,
- private_encryption_payload_t *this, chunk_t assoc)
-{
- chunk_t iv, plain, padding, icv, crypt;
- size_t bs;
-
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "decrypting encryption payload failed, transform missing");
- return INVALID_STATE;
- }
-
- /* prepare data to authenticate-decrypt:
- * | IV | plain | padding | ICV |
- * \____crypt______/ ^
- * | /
- * v /
- * assoc -> + ------->/
- */
-
- bs = this->aead->get_block_size(this->aead);
- iv.len = this->aead->get_iv_size(this->aead);
- iv.ptr = this->encrypted.ptr;
- icv.len = this->aead->get_icv_size(this->aead);
- icv.ptr = this->encrypted.ptr + this->encrypted.len - icv.len;
- crypt.ptr = iv.ptr + iv.len;
- crypt.len = this->encrypted.len - iv.len;
-
- if (iv.len + icv.len > this->encrypted.len ||
- (crypt.len - icv.len) % bs)
- {
- DBG1(DBG_ENC, "decrypting encryption payload failed, invalid length");
- return FAILED;
- }
-
- assoc = append_header(this, assoc);
-
- DBG3(DBG_ENC, "encryption payload decryption:");
- DBG3(DBG_ENC, "IV %B", &iv);
- DBG3(DBG_ENC, "encrypted %B", &crypt);
- DBG3(DBG_ENC, "ICV %B", &icv);
- DBG3(DBG_ENC, "assoc %B", &assoc);
-
- if (!this->aead->decrypt(this->aead, crypt, assoc, iv, NULL))
- {
- DBG1(DBG_ENC, "verifying encryption payload integrity failed");
- free(assoc.ptr);
- return FAILED;
- }
- free(assoc.ptr);
-
- plain = chunk_create(crypt.ptr, crypt.len - icv.len);
- padding.len = plain.ptr[plain.len - 1] + 1;
- if (padding.len > plain.len)
- {
- DBG1(DBG_ENC, "decrypting encryption payload failed, "
- "padding invalid %B", &crypt);
- return PARSE_ERROR;
- }
- plain.len -= padding.len;
- padding.ptr = plain.ptr + plain.len;
-
- DBG3(DBG_ENC, "plain %B", &plain);
- DBG3(DBG_ENC, "padding %B", &padding);
-
- return parse(this, plain);
-}
-
-METHOD(encryption_payload_t, decrypt_v1, status_t,
- private_encryption_payload_t *this, chunk_t iv)
-{
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "decryption failed, transform missing");
- return INVALID_STATE;
- }
-
- /* data must be a multiple of block size */
- if (iv.len != this->aead->get_block_size(this->aead) ||
- this->encrypted.len < iv.len || this->encrypted.len % iv.len)
- {
- DBG1(DBG_ENC, "decryption failed, invalid length");
- return FAILED;
- }
-
- DBG3(DBG_ENC, "decrypting payloads:");
- DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
-
- if (!this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
- {
- return FAILED;
- }
-
- DBG3(DBG_ENC, "plain %B", &this->encrypted);
-
- return parse(this, this->encrypted);
-}
-
-METHOD(encryption_payload_t, set_transform, void,
- private_encryption_payload_t *this, aead_t* aead)
-{
- this->aead = aead;
-}
-
-METHOD2(payload_t, encryption_payload_t, destroy, void,
- private_encryption_payload_t *this)
-{
- this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
- free(this->encrypted.ptr);
- free(this);
-}
-
-/*
- * Described in header
- */
-encryption_payload_t *encryption_payload_create(payload_type_t type)
-{
- private_encryption_payload_t *this;
-
- INIT(this,
- .public = {
- .payload_interface = {
- .verify = _verify,
- .get_encoding_rules = _get_encoding_rules,
- .get_header_length = _get_header_length,
- .get_length = _get_length,
- .get_next_type = _get_next_type,
- .set_next_type = _set_next_type,
- .get_type = _get_type,
- .destroy = _destroy,
- },
- .get_length = _get_length,
- .add_payload = _add_payload,
- .remove_payload = _remove_payload,
- .set_transform = _set_transform,
- .encrypt = _encrypt,
- .decrypt = _decrypt,
- .destroy = _destroy,
- },
- .next_payload = PL_NONE,
- .payloads = linked_list_create(),
- .type = type,
- );
- this->payload_length = get_header_length(this);
-
- if (type == PLV1_ENCRYPTED)
- {
- this->public.encrypt = _encrypt_v1;
- this->public.decrypt = _decrypt_v1;
- }
-
- return &this->public;
-}
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
index 7015667ee..c96738a34 100644
--- a/src/libcharon/encoding/payloads/ike_header.c
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -210,8 +210,9 @@ METHOD(payload_t, verify, status_t,
case TRANSACTION:
case QUICK_MODE:
case NEW_GROUP_MODE:
- if (this->maj_version != IKEV1_MAJOR_VERSION)
+ if (this->maj_version == IKEV2_MAJOR_VERSION)
{
+ /* IKEv1 exchange type in IKEv2? */
return FAILED;
}
break;
@@ -223,14 +224,20 @@ METHOD(payload_t, verify, status_t,
#ifdef ME
case ME_CONNECT:
#endif /* ME */
- if (this->maj_version != IKEV2_MAJOR_VERSION)
+ if (this->maj_version == IKEV1_MAJOR_VERSION)
{
+ /* IKEv2 exchange type in IKEv1? */
return FAILED;
}
break;
default:
- /* unsupported exchange type */
- return FAILED;
+ if (this->maj_version == IKEV1_MAJOR_VERSION ||
+ this->maj_version == IKEV2_MAJOR_VERSION)
+ {
+ /* unsupported exchange type for known version */
+ return FAILED;
+ }
+ break;
}
if (this->initiator_spi == 0)
{
@@ -501,4 +508,3 @@ ike_header_t *ike_header_create_version(int major, int minor)
}
return this;
}
-
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index dd92e429a..94723ddd7 100644
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_
"ME_CONNECT_FAILED");
ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_NOTIFY_STATUS");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IFOM_CAPABILITY, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS,
"INITIAL_CONTACT",
"SET_WINDOW_SIZE",
"ADDITIONAL_TS_POSSIBLE",
@@ -110,8 +110,10 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IFOM_CAPABILITY, MS_NOTIFY_STATUS,
"PSK_PERSIST",
"PSK_CONFIRM",
"ERX_SUPPORTED",
- "IFOM_CAPABILITY");
-ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IFOM_CAPABILITY,
+ "IFOM_CAPABILITY",
+ "SENDER_REQUEST_ID",
+ "FRAGMENTATION_SUPPORTED");
+ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD_R_U_THERE",
@@ -128,7 +130,7 @@ ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
"ME_CONNECTKEY",
"ME_CONNECTAUTH",
"ME_RESPONSE",
- "RADIUS_ATTRIBUTE",);
+ "RADIUS_ATTRIBUTE");
ENUM_END(notify_type_names, RADIUS_ATTRIBUTE);
@@ -172,7 +174,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S
"ME_CONN_FAIL");
ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
"MS_STATUS");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IFOM_CAPABILITY, MS_NOTIFY_STATUS,
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, FRAGMENTATION_SUPPORTED, MS_NOTIFY_STATUS,
"INIT_CONTACT",
"SET_WINSIZE",
"ADD_TS_POSS",
@@ -217,8 +219,10 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IFOM_CAPABILITY, MS_NOTIFY_S
"PSK_PST",
"PSK_CFM",
"ERX_SUP",
- "IFOM_CAP");
-ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IFOM_CAPABILITY,
+ "IFOM_CAP",
+ "SENDER_REQ_ID",
+ "FRAG_SUP");
+ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, FRAGMENTATION_SUPPORTED,
"INITIAL_CONTACT");
ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
"DPD",
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index 3c56f0673..25521c2bb 100644
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -147,6 +147,10 @@ enum notify_type_t {
ERX_SUPPORTED = 16427,
/* IFOM capability, 3GPP TS 24.303, annex B.2 */
IFOM_CAPABILITY = 16428,
+ /* SENDER_REQUEST_ID (draft-yeung-g-ikev2) */
+ SENDER_REQUEST_ID = 16429,
+ /* IKEv2 fragmentation supported, RFC 7383 */
+ FRAGMENTATION_SUPPORTED = 16430,
/* IKEv1 initial contact */
INITIAL_CONTACT_IKEV1 = 24578,
/* IKEv1 DPD */
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index fd616620d..600b6dd68 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -28,7 +28,8 @@
#include <encoding/payloads/auth_payload.h>
#include <encoding/payloads/cert_payload.h>
#include <encoding/payloads/certreq_payload.h>
-#include <encoding/payloads/encryption_payload.h>
+#include <encoding/payloads/encrypted_payload.h>
+#include <encoding/payloads/encrypted_fragment_payload.h>
#include <encoding/payloads/ts_payload.h>
#include <encoding/payloads/delete_payload.h>
#include <encoding/payloads/vendor_id_payload.h>
@@ -59,7 +60,7 @@ ENUM_NEXT(payload_type_names, PLV1_SECURITY_ASSOCIATION, PLV1_CONFIGURATION, PL_
ENUM_NEXT(payload_type_names, PLV1_NAT_D, PLV1_NAT_OA, PLV1_CONFIGURATION,
"NAT_D_V1",
"NAT_OA_V1");
-ENUM_NEXT(payload_type_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_NAT_OA,
+ENUM_NEXT(payload_type_names, PLV2_SECURITY_ASSOCIATION, PLV2_FRAGMENT, PLV1_NAT_OA,
"SECURITY_ASSOCIATION",
"KEY_EXCHANGE",
"ID_INITIATOR",
@@ -76,16 +77,20 @@ ENUM_NEXT(payload_type_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_NAT_OA,
"ENCRYPTED",
"CONFIGURATION",
"EAP",
- "GSPM");
+ "GSPM",
+ "GROUP_ID",
+ "GROUP_SECURITY_ASSOCIATION",
+ "KEY_DOWNLOAD",
+ "ENCRYPTED_FRAGMENT");
#ifdef ME
-ENUM_NEXT(payload_type_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_GSPM,
+ENUM_NEXT(payload_type_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_FRAGMENT,
"ID_PEER");
ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER,
"NAT_D_DRAFT_V1",
"NAT_OA_DRAFT_V1",
"FRAGMENT");
#else
-ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_GSPM,
+ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_FRAGMENT,
"NAT_D_DRAFT_V1",
"NAT_OA_DRAFT_V1",
"FRAGMENT");
@@ -125,7 +130,7 @@ ENUM_NEXT(payload_type_short_names, PLV1_SECURITY_ASSOCIATION, PLV1_CONFIGURATIO
ENUM_NEXT(payload_type_short_names, PLV1_NAT_D, PLV1_NAT_OA, PLV1_CONFIGURATION,
"NAT-D",
"NAT-OA");
-ENUM_NEXT(payload_type_short_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_NAT_OA,
+ENUM_NEXT(payload_type_short_names, PLV2_SECURITY_ASSOCIATION, PLV2_FRAGMENT, PLV1_NAT_OA,
"SA",
"KE",
"IDi",
@@ -142,16 +147,20 @@ ENUM_NEXT(payload_type_short_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_N
"E",
"CP",
"EAP",
- "GSPM");
+ "GSPM",
+ "IDg",
+ "GSA",
+ "KD",
+ "EF");
#ifdef ME
-ENUM_NEXT(payload_type_short_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_GSPM,
+ENUM_NEXT(payload_type_short_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_FRAGMENT,
"IDp");
ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER,
"NAT-D",
"NAT-OA",
"FRAG");
#else
-ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_GSPM,
+ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_FRAGMENT,
"NAT-D",
"NAT-OA",
"FRAG");
@@ -244,9 +253,11 @@ payload_t *payload_create(payload_type_t type)
return (payload_t*)eap_payload_create();
case PLV2_ENCRYPTED:
case PLV1_ENCRYPTED:
- return (payload_t*)encryption_payload_create(type);
+ return (payload_t*)encrypted_payload_create(type);
case PLV1_FRAGMENT:
return (payload_t*)fragment_payload_create();
+ case PLV2_FRAGMENT:
+ return (payload_t*)encrypted_fragment_payload_create();
default:
return (payload_t*)unknown_payload_create(type);
}
@@ -261,15 +272,19 @@ bool payload_is_known(payload_type_t type)
{
return TRUE;
}
- if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP)
+ if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION)
{
return TRUE;
}
- if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION)
+ if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA)
{
return TRUE;
}
- if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA)
+ if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP)
+ {
+ return TRUE;
+ }
+ if (type == PLV2_FRAGMENT)
{
return TRUE;
}
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index d9dd619f7..036cd422d 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -193,7 +193,7 @@ enum payload_type_t {
PLV2_TS_RESPONDER = 45,
/**
- * Encryption payload, contains other payloads (E).
+ * Encrypted payload, contains other payloads (E).
*/
PLV2_ENCRYPTED = 46,
@@ -212,6 +212,26 @@ enum payload_type_t {
*/
PLV2_GSPM = 49,
+ /**
+ * Group Identification (draft-yeung-g-ikev2)
+ */
+ PLV2_IDG = 50,
+
+ /**
+ * Group Security Association (draft-yeung-g-ikev2)
+ */
+ PLV2_GSA = 51,
+
+ /**
+ * Key Download (draft-yeung-g-ikev2)
+ */
+ PLV2_KD = 52,
+
+ /**
+ * Encrypted fragment payload (SKF), RFC 7383
+ */
+ PLV2_FRAGMENT = 53,
+
#ifdef ME
/**
* Identification payload for peers has a value from
@@ -231,7 +251,7 @@ enum payload_type_t {
PLV1_NAT_OA_DRAFT_00_03 = 131,
/**
- * IKE fragment (proprietary IKEv1 extension)
+ * IKEv1 fragment (proprietary IKEv1 extension)
*/
PLV1_FRAGMENT = 132,
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 8e3a01285..407038a2d 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2014 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -296,7 +296,7 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
linked_list_t *substructs, *list;
if (this->type == PLV1_SECURITY_ASSOCIATION)
- { /* IKEv1 proposals start with 0 */
+ { /* IKEv1 proposals may start with 0 or 1 (or any other number really) */
struct_number = ignore_struct_number = -1;
}
@@ -309,17 +309,22 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
enumerator = this->proposals->create_enumerator(this->proposals);
while (enumerator->enumerate(enumerator, &substruct))
{
+ int current_number = substruct->get_proposal_number(substruct);
+
/* check if a proposal has a single protocol */
- if (substruct->get_proposal_number(substruct) == struct_number)
+ if (current_number == struct_number)
{
if (ignore_struct_number < struct_number)
- { /* remove an already added, if first of series */
+ { /* remove an already added substruct, if first of series */
substructs->remove_last(substructs, (void**)&substruct);
ignore_struct_number = struct_number;
}
continue;
}
- struct_number++;
+ /* for IKEv1 the numbers don't have to be consecutive, for IKEv2 they do
+ * but since we don't really care for the actual number we accept them
+ * anyway. we already verified that they increase monotonically. */
+ struct_number = current_number;
substructs->insert_last(substructs, substruct);
}
enumerator->destroy(enumerator);
@@ -364,7 +369,7 @@ METHOD(sa_payload_t, get_ipcomp_proposals, linked_list_t*,
}
if (proposal_number != current_proposal)
{ /* start of a new proposal */
- if (espah && ipcomp)
+ if (espah && ipcomp && ipcomp->get_cpi(ipcomp, NULL))
{ /* previous proposal is valid */
break;
}
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index a2a3b1f89..5ce9471bd 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -524,8 +524,7 @@ static job_requeue_t receive_packets(private_receiver_t *this)
#ifdef USE_IKEV2
send_notify(message, IKEV2_MAJOR_VERSION, INFORMATIONAL,
INVALID_MAJOR_VERSION, chunk_empty);
-#endif /* USE_IKEV2 */
-#ifdef USE_IKEV1
+#elif defined(USE_IKEV1)
send_notify(message, IKEV1_MAJOR_VERSION, INFORMATIONAL_V1,
INVALID_MAJOR_VERSION, chunk_empty);
#endif /* USE_IKEV1 */
@@ -684,4 +683,3 @@ receiver_t *receiver_create()
return &this->public;
}
-
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 0655959ca..c3b014c3c 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index 287c94acc..50594a452 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 9fd515073..700a4219c 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index edda93e77..08101d51d 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index 5670f4323..679d2dae6 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index da364b06e..768c2b32b 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -233,6 +233,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -293,6 +294,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -358,6 +360,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -405,6 +409,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index d408cd24e..3484e08a3 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 97432f1b1..381d7a119 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -242,6 +242,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -302,6 +303,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -367,6 +369,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -414,6 +418,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 5b20fe5a6..3b0f8763c 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index d0ee19899..839a379ea 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index 78b66ac96..fdbad6234 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 7f18792c4..9675104da 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -234,6 +234,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -294,6 +295,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -359,6 +361,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -406,6 +410,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index 5275a348c..0610b5859 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index 5dd623d6e..38c9d0b7c 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -234,6 +234,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -294,6 +295,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -359,6 +361,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -406,6 +410,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index c0e42198c..f5dfd6814 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 615a916c1..5ccd58158 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index cd4355dfa..04cc422f5 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index 6719497d3..60d12dc1d 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -414,6 +414,30 @@ static void add_unity_attribute(eap_radius_provider_t *provider, u_int32_t id,
}
/**
+ * Add a DNS/NBNS configuration attribute
+ */
+static void add_nameserver_attribute(eap_radius_provider_t *provider,
+ u_int32_t id, int type, chunk_t data)
+{
+ /* these are from different vendors, but there is currently no conflict */
+ switch (type)
+ {
+ case 5: /* CVPN3000-Primary-DNS */
+ case 6: /* CVPN3000-Secondary-DNS */
+ case 28: /* MS-Primary-DNS-Server */
+ case 29: /* MS-Secondary-DNS-Server */
+ provider->add_attribute(provider, id, INTERNAL_IP4_DNS, data);
+ break;
+ case 7: /* CVPN3000-Primary-WINS */
+ case 8: /* CVPN3000-Secondary-WINS */
+ case 30: /* MS-Primary-NBNS-Server */
+ case 31: /* MS-Secondary-NBNS-Server */
+ provider->add_attribute(provider, id, INTERNAL_IP4_NBNS, data);
+ break;
+ }
+}
+
+/**
* Add a UNITY_LOCAL_LAN or UNITY_SPLIT_INCLUDE attribute
*/
static void add_unity_split_attribute(eap_radius_provider_t *provider,
@@ -515,6 +539,16 @@ static void process_cfg_attributes(radius_message_t *msg)
{
switch (type)
{
+ case 5: /* CVPN3000-Primary-DNS */
+ case 6: /* CVPN3000-Secondary-DNS */
+ case 7: /* CVPN3000-Primary-WINS */
+ case 8: /* CVPN3000-Secondary-WINS */
+ if (data.len == 4)
+ {
+ add_nameserver_attribute(provider,
+ ike_sa->get_unique_id(ike_sa), type, data);
+ }
+ break;
case 15: /* CVPN3000-IPSec-Banner1 */
case 28: /* CVPN3000-IPSec-Default-Domain */
case 29: /* CVPN3000-IPSec-Split-DNS-Names */
@@ -546,6 +580,22 @@ static void process_cfg_attributes(radius_message_t *msg)
break;
}
}
+ if (vendor == PEN_MICROSOFT)
+ {
+ switch (type)
+ {
+ case 28: /* MS-Primary-DNS-Server */
+ case 29: /* MS-Secondary-DNS-Server */
+ case 30: /* MS-Primary-NBNS-Server */
+ case 31: /* MS-Secondary-NBNS-Server */
+ if (data.len == 4)
+ {
+ add_nameserver_attribute(provider,
+ ike_sa->get_unique_id(ike_sa), type, data);
+ }
+ break;
+ }
+ }
}
enumerator->destroy(enumerator);
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 0020c5d57..31c96d229 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -488,6 +488,16 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
message->add(message, RAT_ACCT_SESSION_ID,
chunk_create(entry->sid, strlen(entry->sid)));
+ if (!entry->interim.interval)
+ {
+ entry->interim.interval = lib->settings->get_time(lib->settings,
+ "%s.plugins.eap-radius.accounting_interval", 0, lib->ns);
+ if (entry->interim.interval)
+ {
+ DBG1(DBG_CFG, "scheduling RADIUS Interim-Updates every %us",
+ entry->interim.interval);
+ }
+ }
schedule_interim(this, entry);
this->mutex->unlock(this->mutex);
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index 494efd99a..6a00ea74d 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index 82e7561f8..7a08f4e0e 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 9a7a1909e..a1ec7adc1 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -238,6 +238,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -298,6 +299,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -363,6 +365,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -410,6 +414,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 886b0c575..bf99ab095 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -238,6 +238,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -298,6 +299,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -363,6 +365,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -410,6 +414,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 57c64246b..ce4602365 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index eb4d3fa95..0c0b7fd52 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index c63d56b53..25696f524 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index 97552dfd0..2d5d65875 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index 70cc18405..38c7632ac 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 0782dde53..d9fa454ca 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -243,6 +243,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -303,6 +304,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -368,6 +370,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -415,6 +419,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/ext_auth/Makefile.am b/src/libcharon/plugins/ext_auth/Makefile.am
new file mode 100644
index 000000000..d51ea8881
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-ext-auth.la
+else
+plugin_LTLIBRARIES = libstrongswan-ext-auth.la
+endif
+
+libstrongswan_ext_auth_la_SOURCES = ext_auth_plugin.h ext_auth_plugin.c \
+ ext_auth_listener.h ext_auth_listener.c
+
+libstrongswan_ext_auth_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/ext_auth/Makefile.in b/src/libcharon/plugins/ext_auth/Makefile.in
new file mode 100644
index 000000000..a1b47dd33
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/Makefile.in
@@ -0,0 +1,774 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/ext_auth
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_ext_auth_la_LIBADD =
+am_libstrongswan_ext_auth_la_OBJECTS = ext_auth_plugin.lo \
+ ext_auth_listener.lo
+libstrongswan_ext_auth_la_OBJECTS = \
+ $(am_libstrongswan_ext_auth_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libstrongswan_ext_auth_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_ext_auth_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_ext_auth_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_ext_auth_la_rpath =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstrongswan_ext_auth_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_ext_auth_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libhydra \
+ -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-ext-auth.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-ext-auth.la
+libstrongswan_ext_auth_la_SOURCES = ext_auth_plugin.h ext_auth_plugin.c \
+ ext_auth_listener.h ext_auth_listener.c
+
+libstrongswan_ext_auth_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/ext_auth/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/ext_auth/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libstrongswan-ext-auth.la: $(libstrongswan_ext_auth_la_OBJECTS) $(libstrongswan_ext_auth_la_DEPENDENCIES) $(EXTRA_libstrongswan_ext_auth_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_ext_auth_la_LINK) $(am_libstrongswan_ext_auth_la_rpath) $(libstrongswan_ext_auth_la_OBJECTS) $(libstrongswan_ext_auth_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_auth_listener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_auth_plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-pluginLTLIBRARIES install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-pluginLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_listener.c b/src/libcharon/plugins/ext_auth/ext_auth_listener.c
new file mode 100644
index 000000000..06cec20d7
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_listener.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* for vasprintf() */
+#define _GNU_SOURCE
+#include "ext_auth_listener.h"
+
+#include <daemon.h>
+#include <utils/process.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+typedef struct private_ext_auth_listener_t private_ext_auth_listener_t;
+
+/**
+ * Private data of an ext_auth_listener_t object.
+ */
+struct private_ext_auth_listener_t {
+
+ /**
+ * Public ext_auth_listener_listener_t interface.
+ */
+ ext_auth_listener_t public;
+
+ /**
+ * Path to authorization program
+ */
+ char *script;
+};
+
+/**
+ * Allocate and push a format string to the environment
+ */
+static bool push_env(char *envp[], u_int count, char *fmt, ...)
+{
+ int i = 0;
+ char *str;
+ va_list args;
+
+ while (envp[i])
+ {
+ if (++i + 1 >= count)
+ {
+ return FALSE;
+ }
+ }
+ va_start(args, fmt);
+ if (vasprintf(&str, fmt, args) >= 0)
+ {
+ envp[i] = str;
+ }
+ va_end(args);
+ return envp[i] != NULL;
+}
+
+/**
+ * Free all allocated environment strings
+ */
+static void free_env(char *envp[])
+{
+ int i;
+
+ for (i = 0; envp[i]; i++)
+ {
+ free(envp[i]);
+ }
+}
+
+METHOD(listener_t, authorize, bool,
+ private_ext_auth_listener_t *this, ike_sa_t *ike_sa,
+ bool final, bool *success)
+{
+ if (final)
+ {
+ FILE *shell;
+ process_t *process;
+ char *envp[32] = {};
+ int out, retval;
+
+ *success = FALSE;
+
+ push_env(envp, countof(envp), "IKE_UNIQUE_ID=%u",
+ ike_sa->get_unique_id(ike_sa));
+ push_env(envp, countof(envp), "IKE_NAME=%s",
+ ike_sa->get_name(ike_sa));
+
+ push_env(envp, countof(envp), "IKE_LOCAL_HOST=%H",
+ ike_sa->get_my_host(ike_sa));
+ push_env(envp, countof(envp), "IKE_REMOTE_HOST=%H",
+ ike_sa->get_other_host(ike_sa));
+
+ push_env(envp, countof(envp), "IKE_LOCAL_ID=%Y",
+ ike_sa->get_my_id(ike_sa));
+ push_env(envp, countof(envp), "IKE_REMOTE_ID=%Y",
+ ike_sa->get_other_id(ike_sa));
+
+ if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
+ ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
+ {
+ push_env(envp, countof(envp), "IKE_REMOTE_EAP_ID=%Y",
+ ike_sa->get_other_eap_id(ike_sa));
+ }
+
+ process = process_start_shell(envp, NULL, &out, NULL,
+ "2>&1 %s", this->script);
+ if (process)
+ {
+ shell = fdopen(out, "r");
+ if (shell)
+ {
+ while (TRUE)
+ {
+ char resp[128], *e;
+
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_CFG, "error reading from ext-auth script");
+ }
+ break;
+ }
+ else
+ {
+ e = resp + strlen(resp);
+ if (e > resp && e[-1] == '\n')
+ {
+ e[-1] = '\0';
+ }
+ DBG1(DBG_CHD, "ext-auth: %s", resp);
+ }
+ }
+ fclose(shell);
+ }
+ else
+ {
+ close(out);
+ }
+ if (process->wait(process, &retval))
+ {
+ if (retval == EXIT_SUCCESS)
+ {
+ *success = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_CFG, "rejecting IKE_SA for ext-auth result: %d",
+ retval);
+ }
+ }
+ }
+ free_env(envp);
+ }
+ return TRUE;
+}
+
+METHOD(ext_auth_listener_t, destroy, void,
+ private_ext_auth_listener_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+ext_auth_listener_t *ext_auth_listener_create(char *script)
+{
+ private_ext_auth_listener_t *this;
+
+ INIT(this,
+ .public = {
+ .listener = {
+ .authorize = _authorize,
+ },
+ .destroy = _destroy,
+ },
+ .script = script,
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_listener.h b/src/libcharon/plugins/ext_auth/ext_auth_listener.h
new file mode 100644
index 000000000..3fec83066
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_listener.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup ext_auth_listener ext_auth_listener
+ * @{ @ingroup ext_auth
+ */
+
+#ifndef EXT_AUTH_LISTENER_H_
+#define EXT_AUTH_LISTENER_H_
+
+#include <bus/listeners/listener.h>
+
+typedef struct ext_auth_listener_t ext_auth_listener_t;
+
+/**
+ * Listener using an external script to authorize connection
+ */
+struct ext_auth_listener_t {
+
+ /**
+ * Implements listener_t interface.
+ */
+ listener_t listener;
+
+ /**
+ * Destroy the listener.
+ */
+ void (*destroy)(ext_auth_listener_t *this);
+};
+
+/**
+ * Create ext_auth_listener instance.
+ *
+ * @param script path to authorization script
+ * @return listener instance
+ */
+ext_auth_listener_t *ext_auth_listener_create(char *script);
+
+#endif /** ext_auth_LISTENER_H_ @}*/
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_plugin.c b/src/libcharon/plugins/ext_auth/ext_auth_plugin.c
new file mode 100644
index 000000000..b3698c767
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_plugin.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "ext_auth_plugin.h"
+#include "ext_auth_listener.h"
+
+#include <daemon.h>
+
+typedef struct private_ext_auth_plugin_t private_ext_auth_plugin_t;
+
+/**
+ * private data of ext_auth plugin
+ */
+struct private_ext_auth_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ ext_auth_plugin_t public;
+
+ /**
+ * Listener verifying peers during authorization
+ */
+ ext_auth_listener_t *listener;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_ext_auth_plugin_t *this)
+{
+ return "ext-auth";
+}
+
+/**
+ * Create a listener instance, NULL on error
+ */
+static ext_auth_listener_t* create_listener()
+{
+ char *script;
+
+ script = lib->settings->get_str(lib->settings,
+ "%s.plugins.ext-auth.script", NULL, lib->ns);
+ if (!script)
+ {
+ DBG1(DBG_CFG, "no script for ext-auth script defined, disabled");
+ return NULL;
+ }
+ DBG1(DBG_CFG, "using ext-auth script '%s'", script);
+ return ext_auth_listener_create(script);
+}
+
+/**
+ * Register listener
+ */
+static bool plugin_cb(private_ext_auth_plugin_t *this,
+ plugin_feature_t *feature, bool reg, void *cb_data)
+{
+ if (reg)
+ {
+ this->listener = create_listener();
+ if (!this->listener)
+ {
+ return FALSE;
+ }
+ charon->bus->add_listener(charon->bus, &this->listener->listener);
+ }
+ else
+ {
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+ }
+ return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+ private_ext_auth_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
+ PLUGIN_PROVIDE(CUSTOM, "ext_auth"),
+ };
+ *features = f;
+ return countof(f);
+}
+
+
+METHOD(plugin_t, reload, bool,
+ private_ext_auth_plugin_t *this)
+{
+ ext_auth_listener_t *listener;
+
+ /* reload new listener overlapped */
+ listener = create_listener();
+ if (listener)
+ {
+ charon->bus->add_listener(charon->bus, &listener->listener);
+ }
+ if (this->listener)
+ {
+ charon->bus->remove_listener(charon->bus, &this->listener->listener);
+ this->listener->destroy(this->listener);
+ }
+ this->listener = listener;
+
+ return TRUE;
+}
+
+METHOD(plugin_t, destroy, void,
+ private_ext_auth_plugin_t *this)
+{
+ free(this);
+}
+
+/**
+ * Plugin constructor
+ */
+plugin_t *ext_auth_plugin_create()
+{
+ private_ext_auth_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .reload = _reload,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/ext_auth/ext_auth_plugin.h b/src/libcharon/plugins/ext_auth/ext_auth_plugin.h
new file mode 100644
index 000000000..1288e240c
--- /dev/null
+++ b/src/libcharon/plugins/ext_auth/ext_auth_plugin.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 Vyronas Tsingaras (vtsingaras@it.auth.gr)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @defgroup ext_auth ext_auth
+ * @ingroup cplugins
+ *
+ * @defgroup ext_auth_plugin ext_auth_plugin
+ * @{ @ingroup ext_auth
+ */
+
+#ifndef EXT_AUTH_PLUGIN_H_
+#define EXT_AUTH_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct ext_auth_plugin_t ext_auth_plugin_t;
+
+/**
+ * Plugin using an external script to authorize connections.
+ */
+struct ext_auth_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** EXT_AUTH_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 75ff158a8..2bfd38ba1 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -233,6 +233,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -293,6 +294,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -358,6 +360,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -405,6 +409,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index cec73620a..aa5bdb747 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 6ff24c334..e20e872c1 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -437,11 +437,13 @@ static void process_ike_update(private_ha_dispatcher_t *this,
pools->destroy(pools);
}
}
+#ifdef USE_IKEV1
if (ike_sa->get_version(ike_sa) == IKEV1)
{
lib->processor->queue_job(lib->processor, (job_t*)
adopt_children_job_create(ike_sa->get_id(ike_sa)));
}
+#endif /* USE_IKEV1 */
this->cache->cache(this->cache, ike_sa, message);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index da2e8d7fb..bd3fd63aa 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
index 460c7b730..7e1f79bd8 100644
--- a/src/libcharon/plugins/kernel_iph/Makefile.in
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index a4e5ba931..c961c0bd8 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
index ff987f8d4..1c92e30fc 100644
--- a/src/libcharon/plugins/kernel_wfp/Makefile.in
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -243,6 +243,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -303,6 +304,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -368,6 +370,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -415,6 +419,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index 78ec6660e..db4552dde 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -232,6 +232,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -292,6 +293,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -357,6 +359,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -404,6 +408,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index df75c0f4b..418dccba5 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -245,6 +245,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -305,6 +306,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -370,6 +372,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -417,6 +421,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index deb517ed8..f0f2c75f4 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -241,6 +241,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -301,6 +302,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -366,6 +368,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -413,6 +417,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index aa3ade079..3a866e968 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index 919b936c0..e0f70ce44 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index ce81fb1a8..adb61e817 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index 870b42790..a0c21c442 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index 35ebf9975..14abba99a 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index 35e7f2a87..7c5b030f4 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -233,6 +233,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -293,6 +294,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -358,6 +360,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -405,6 +409,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index bee1259e6..548524a38 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index 081d3efc7..9cc39955b 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -45,9 +45,6 @@
#include <daemon.h>
#include <threading/thread.h>
-/* Maximum size of a packet */
-#define MAX_PACKET 10000
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -739,7 +736,7 @@ socket_default_socket_t *socket_default_socket_create()
.natt = lib->settings->get_int(lib->settings,
"%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
.max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, lib->ns),
+ "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
.set_source = lib->settings->get_bool(lib->settings,
"%s.plugins.socket-default.set_source", TRUE,
lib->ns),
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index 073806d64..892549c6c 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
index 3161a709f..b82a69e1b 100644
--- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
+++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
@@ -42,9 +42,6 @@
#include <threading/rwlock.h>
#include <collections/hashtable.h>
-/* Maximum size of a packet */
-#define MAX_PACKET 10000
-
/* these are not defined on some platforms */
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
@@ -668,7 +665,7 @@ socket_dynamic_socket_t *socket_dynamic_socket_create()
},
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, lib->ns),
+ "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
);
if (pipe(this->notify) != 0)
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
index ff38e8158..88b2ac3f0 100644
--- a/src/libcharon/plugins/socket_win/Makefile.in
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c
index 5ebe04aac..fbfbedae1 100644
--- a/src/libcharon/plugins/socket_win/socket_win_socket.c
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.c
@@ -25,9 +25,6 @@
#include <mswsock.h>
-/* Maximum size of a packet */
-#define MAX_PACKET 10000
-
/* number of sockets in use */
#define SOCKET_COUNT 2
@@ -458,7 +455,7 @@ socket_win_socket_t *socket_win_socket_create()
"%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
},
.max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, lib->ns),
+ "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
);
for (i = 0; i < SOCKET_COUNT; i++)
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 208b900e1..3c132457b 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -233,6 +233,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -293,6 +294,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -358,6 +360,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -405,6 +409,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 59a59834a..d4680186a 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -237,6 +237,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -297,6 +298,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -362,6 +364,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -409,6 +413,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index f908219ed..83431d17c 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -65,6 +65,11 @@ struct private_stroke_cred_t {
stroke_cred_t public;
/**
+ * secrets file with credential information
+ */
+ char *secrets_file;
+
+ /**
* credentials
*/
mem_cred_t *creds;
@@ -1297,7 +1302,7 @@ METHOD(stroke_cred_t, reread, void,
if (msg->reread.flags & REREAD_SECRETS)
{
DBG1(DBG_CFG, "rereading secrets");
- load_secrets(this, NULL, SECRETS_FILE, 0, prompt);
+ load_secrets(this, NULL, this->secrets_file, 0, prompt);
}
if (msg->reread.flags & REREAD_CACERTS)
{
@@ -1370,6 +1375,9 @@ stroke_cred_t *stroke_cred_create()
.cachecrl = _cachecrl,
.destroy = _destroy,
},
+ .secrets_file = lib->settings->get_str(lib->settings,
+ "%s.plugins.stroke.secrets_file", SECRETS_FILE,
+ lib->ns),
.creds = mem_cred_create(),
);
@@ -1380,7 +1388,7 @@ stroke_cred_t *stroke_cred_create()
FALSE, lib->ns);
load_certs(this);
- load_secrets(this, NULL, SECRETS_FILE, 0, NULL);
+ load_secrets(this, NULL, this->secrets_file, 0, NULL);
return &this->public;
}
diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index 769ad52bc..0e477f9f3 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 51d46a673..3f2952c4b 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -238,6 +238,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -298,6 +299,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -363,6 +365,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -410,6 +414,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 531c00c0c..97c479632 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -239,6 +239,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -299,6 +300,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -364,6 +366,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -411,6 +415,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 948db7e3c..5e16c3c35 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -233,6 +233,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -293,6 +294,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -358,6 +360,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -405,6 +409,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 6e4dbff2b..1aca319c7 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -238,6 +238,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -298,6 +299,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -363,6 +365,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -410,6 +414,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index 4d411f68e..1e04ebced 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -234,6 +234,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -294,6 +295,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -359,6 +361,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -406,6 +410,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c
index 9f72a80da..52a2c7f24 100644
--- a/src/libcharon/plugins/unity/unity_narrow.c
+++ b/src/libcharon/plugins/unity/unity_narrow.c
@@ -139,6 +139,23 @@ static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local)
configured->destroy(configured);
}
+/**
+ * Check if any Split-Include attributes are active on this IKE_SA
+ */
+static bool has_split_includes(private_unity_narrow_t *this, ike_sa_t *ike_sa)
+{
+ enumerator_t *enumerator;
+ traffic_selector_t *ts;
+ bool has;
+
+ enumerator = this->handler->create_include_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ has = enumerator->enumerate(enumerator, &ts);
+ enumerator->destroy(enumerator);
+
+ return has;
+}
+
METHOD(listener_t, narrow, bool,
private_unity_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)
@@ -146,23 +163,43 @@ METHOD(listener_t, narrow, bool,
if (ike_sa->get_version(ike_sa) == IKEV1 &&
ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
{
- switch (type)
+ /* depending on who initiates a rekeying the hooks will not match the
+ * roles in the IKE_SA */
+ if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
{
- case NARROW_INITIATOR_PRE_AUTH:
- narrow_pre(remote, "other");
- break;
- case NARROW_INITIATOR_POST_AUTH:
- narrow_initiator(this, ike_sa,
- child_sa->get_config(child_sa), remote);
- break;
- case NARROW_RESPONDER:
- narrow_pre(local, "us");
- break;
- case NARROW_RESPONDER_POST:
- narrow_responder_post(child_sa->get_config(child_sa), local);
- break;
- default:
- break;
+ switch (type)
+ {
+ case NARROW_INITIATOR_PRE_AUTH:
+ case NARROW_RESPONDER:
+ if (has_split_includes(this, ike_sa))
+ {
+ narrow_pre(remote, "other");
+ }
+ break;
+ case NARROW_INITIATOR_POST_AUTH:
+ case NARROW_RESPONDER_POST:
+ narrow_initiator(this, ike_sa,
+ child_sa->get_config(child_sa), remote);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (type)
+ {
+ case NARROW_INITIATOR_PRE_AUTH:
+ case NARROW_RESPONDER:
+ narrow_pre(local, "us");
+ break;
+ case NARROW_INITIATOR_POST_AUTH:
+ case NARROW_RESPONDER_POST:
+ narrow_responder_post(child_sa->get_config(child_sa), local);
+ break;
+ default:
+ break;
+ }
}
}
return TRUE;
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index b377110ec..834d373f3 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 200f298a1..1d15cc55e 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -16,9 +16,11 @@
#define _GNU_SOURCE
#include <stdio.h>
+#include <unistd.h>
#include "updown_listener.h"
+#include <utils/process.h>
#include <hydra.h>
#include <daemon.h>
#include <config/child_cfg.h>
@@ -97,53 +99,84 @@ static char* uncache_iface(private_updown_listener_t *this, u_int32_t reqid)
}
/**
- * Create variables for handled DNS attributes
+ * Allocate and push a format string to the environment
*/
-static char *make_dns_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+static bool push_env(char *envp[], u_int count, char *fmt, ...)
{
- enumerator_t *enumerator;
- host_t *host;
- int v4 = 0, v6 = 0;
- char total[512] = "", current[64];
+ int i = 0;
+ char *str;
+ va_list args;
- if (!this->handler)
+ while (envp[i])
{
- return strdup("");
+ if (++i + 1 >= count)
+ {
+ return FALSE;
+ }
}
+ va_start(args, fmt);
+ if (vasprintf(&str, fmt, args) >= 0)
+ {
+ envp[i] = str;
+ }
+ va_end(args);
+ return envp[i] != NULL;
+}
- enumerator = this->handler->create_dns_enumerator(this->handler,
- ike_sa->get_unique_id(ike_sa));
- while (enumerator->enumerate(enumerator, &host))
+/**
+ * Free all allocated environment strings
+ */
+static void free_env(char *envp[])
+{
+ int i;
+
+ for (i = 0; envp[i]; i++)
{
- switch (host->get_family(host))
+ free(envp[i]);
+ }
+}
+
+/**
+ * Push variables for handled DNS attributes
+ */
+static void push_dns_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
+ char *envp[], u_int count)
+{
+ enumerator_t *enumerator;
+ host_t *host;
+ int v4 = 0, v6 = 0;
+
+ if (this->handler)
+ {
+ enumerator = this->handler->create_dns_enumerator(this->handler,
+ ike_sa->get_unique_id(ike_sa));
+ while (enumerator->enumerate(enumerator, &host))
{
- case AF_INET:
- snprintf(current, sizeof(current),
- "PLUTO_DNS4_%d='%H' ", ++v4, host);
- break;
- case AF_INET6:
- snprintf(current, sizeof(current),
- "PLUTO_DNS6_%d='%H' ", ++v6, host);
- break;
- default:
- continue;
+ switch (host->get_family(host))
+ {
+ case AF_INET:
+ push_env(envp, count, "PLUTO_DNS4_%d=%H", ++v4, host);
+ break;
+ case AF_INET6:
+ push_env(envp, count, "PLUTO_DNS6_%d=%H", ++v6, host);
+ break;
+ default:
+ continue;
+ }
}
- strncat(total, current, sizeof(total) - strlen(total) - 1);
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
-
- return strdup(total);
}
/**
- * Create variables for local virtual IPs
+ * Push variables for local virtual IPs
*/
-static char *make_vip_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
+static void push_vip_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
+ char *envp[], u_int count)
{
enumerator_t *enumerator;
host_t *host;
int v4 = 0, v6 = 0;
- char total[512] = "", current[64];
bool first = TRUE;
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
@@ -151,28 +184,22 @@ static char *make_vip_vars(private_updown_listener_t *this, ike_sa_t *ike_sa)
{
if (first)
{ /* legacy variable for first VIP */
- snprintf(current, sizeof(current),
- "PLUTO_MY_SOURCEIP='%H' ", host);
- strncat(total, current, sizeof(total) - strlen(total) - 1);
+ first = FALSE;
+ push_env(envp, count, "PLUTO_MY_SOURCEIP=%H", host);
}
switch (host->get_family(host))
{
case AF_INET:
- snprintf(current, sizeof(current),
- "PLUTO_MY_SOURCEIP4_%d='%H' ", ++v4, host);
+ push_env(envp, count, "PLUTO_MY_SOURCEIP4_%d=%H", ++v4, host);
break;
case AF_INET6:
- snprintf(current, sizeof(current),
- "PLUTO_MY_SOURCEIP6_%d='%H' ", ++v6, host);
+ push_env(envp, count, "PLUTO_MY_SOURCEIP6_%d=%H", ++v6, host);
break;
default:
continue;
}
- strncat(total, current, sizeof(total) - strlen(total) - 1);
}
enumerator->destroy(enumerator);
-
- return strdup(total);
}
/**
@@ -196,240 +223,182 @@ static u_int16_t get_port(traffic_selector_t *me,
return local ? me->get_from_port(me) : other->get_from_port(other);
}
-METHOD(listener_t, child_updown, bool,
- private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
- bool up)
+/**
+ * Invoke the updown script once for given traffic selectors
+ */
+static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
+ child_sa_t *child_sa, child_cfg_t *config, bool up,
+ traffic_selector_t *my_ts, traffic_selector_t *other_ts)
{
- traffic_selector_t *my_ts, *other_ts;
- enumerator_t *enumerator;
- child_cfg_t *config;
- host_t *me, *other;
- char *script;
+ host_t *me, *other, *host;
+ char *iface;
+ u_int8_t mask;
+ mark_t mark;
+ bool is_host, is_ipv6;
+ int out;
+ FILE *shell;
+ process_t *process;
+ char *envp[128] = {};
- config = child_sa->get_config(child_sa);
- script = config->get_updown(config);
me = ike_sa->get_my_host(ike_sa);
other = ike_sa->get_other_host(ike_sa);
- if (script == NULL)
+ push_env(envp, countof(envp), "PLUTO_VERSION=1.1");
+ is_host = my_ts->is_host(my_ts, me);
+ if (is_host)
{
- return TRUE;
+ is_ipv6 = me->get_family(me) == AF_INET6;
}
-
- enumerator = child_sa->create_policy_enumerator(child_sa);
- while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+ else
{
- char command[2048];
- host_t *my_client, *other_client;
- u_int8_t my_client_mask, other_client_mask;
- char *virtual_ip, *iface, *mark_in, *mark_out, *udp_enc, *dns, *xauth;
- mark_t mark;
- bool is_host, is_ipv6, use_ipcomp;
- FILE *shell;
-
- my_ts->to_subnet(my_ts, &my_client, &my_client_mask);
- other_ts->to_subnet(other_ts, &other_client, &other_client_mask);
-
- virtual_ip = make_vip_vars(this, ike_sa);
-
- /* 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))
+ is_ipv6 = my_ts->get_type(my_ts) == TS_IPV6_ADDR_RANGE;
+ }
+ push_env(envp, countof(envp), "PLUTO_VERB=%s%s%s",
+ up ? "up" : "down",
+ is_host ? "-host" : "-client",
+ is_ipv6 ? "-v6" : "");
+ push_env(envp, countof(envp), "PLUTO_CONNECTION=%s",
+ config->get_name(config));
+ if (up)
+ {
+ if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+ me, &iface))
{
- if (asprintf(&udp_enc, "PLUTO_UDP_ENC='%u' ",
- other->get_port(other)) < 0)
- {
- udp_enc = NULL;
- }
-
+ cache_iface(this, child_sa->get_reqid(child_sa), iface);
}
else
{
- if (asprintf(&udp_enc, "") < 0)
- {
- udp_enc = NULL;
- }
-
+ iface = NULL;
}
+ }
+ else
+ {
+ iface = uncache_iface(this, child_sa->get_reqid(child_sa));
+ }
+ push_env(envp, countof(envp), "PLUTO_INTERFACE=%s",
+ iface ? iface : "unknown");
+ push_env(envp, countof(envp), "PLUTO_REQID=%u",
+ child_sa->get_reqid(child_sa));
+ push_env(envp, countof(envp), "PLUTO_PROTO=%s",
+ child_sa->get_protocol(child_sa) == PROTO_ESP ? "esp" : "ah");
+ push_env(envp, countof(envp), "PLUTO_UNIQUEID=%u",
+ ike_sa->get_unique_id(ike_sa));
+ push_env(envp, countof(envp), "PLUTO_ME=%H", me);
+ push_env(envp, countof(envp), "PLUTO_MY_ID=%Y", ike_sa->get_my_id(ike_sa));
+ if (my_ts->to_subnet(my_ts, &host, &mask))
+ {
+ push_env(envp, countof(envp), "PLUTO_MY_CLIENT=%+H/%u", host, mask);
+ host->destroy(host);
+ }
+ push_env(envp, countof(envp), "PLUTO_MY_PORT=%u",
+ get_port(my_ts, other_ts, TRUE));
+ push_env(envp, countof(envp), "PLUTO_MY_PROTOCOL=%u",
+ my_ts->get_protocol(my_ts));
+ push_env(envp, countof(envp), "PLUTO_PEER=%H", other);
+ push_env(envp, countof(envp), "PLUTO_PEER_ID=%Y",
+ ike_sa->get_other_id(ike_sa));
+ if (other_ts->to_subnet(other_ts, &host, &mask))
+ {
+ push_env(envp, countof(envp), "PLUTO_PEER_CLIENT=%+H/%u", host, mask);
+ host->destroy(host);
+ }
+ push_env(envp, countof(envp), "PLUTO_PEER_PORT=%u",
+ get_port(my_ts, other_ts, FALSE));
+ push_env(envp, countof(envp), "PLUTO_PEER_PROTOCOL=%u",
+ other_ts->get_protocol(other_ts));
+ if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
+ ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
+ {
+ push_env(envp, countof(envp), "PLUTO_XAUTH_ID=%Y",
+ ike_sa->get_other_eap_id(ike_sa));
+ }
+ push_vip_env(this, ike_sa, envp, countof(envp));
+ mark = config->get_mark(config, TRUE);
+ if (mark.value)
+ {
+ push_env(envp, countof(envp), "PLUTO_MARK_IN=%u/0x%08x",
+ mark.value, mark.mask);
+ }
+ mark = config->get_mark(config, FALSE);
+ if (mark.value)
+ {
+ push_env(envp, countof(envp), "PLUTO_MARK_OUT=%u/0x%08x",
+ mark.value, mark.mask);
+ }
+ if (ike_sa->has_condition(ike_sa, COND_NAT_ANY))
+ {
+ push_env(envp, countof(envp), "PLUTO_UDP_ENC=%u",
+ other->get_port(other));
+ }
+ if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE)
+ {
+ push_env(envp, countof(envp), "PLUTO_IPCOMP=1");
+ }
+ push_dns_env(this, ike_sa, envp, countof(envp));
+ if (config->get_hostaccess(config))
+ {
+ push_env(envp, countof(envp), "PLUTO_HOST_ACCESS=1");
+ }
- if (ike_sa->has_condition(ike_sa, COND_EAP_AUTHENTICATED) ||
- ike_sa->has_condition(ike_sa, COND_XAUTH_AUTHENTICATED))
- {
- if (asprintf(&xauth, "PLUTO_XAUTH_ID='%Y' ",
- ike_sa->get_other_eap_id(ike_sa)) < 0)
- {
- xauth = NULL;
- }
- }
- else
+ process = process_start_shell(envp, NULL, &out, NULL, "2>&1 %s",
+ config->get_updown(config));
+ if (process)
+ {
+ shell = fdopen(out, "r");
+ if (shell)
{
- if (asprintf(&xauth, "") < 0)
+ while (TRUE)
{
- xauth = NULL;
- }
- }
+ char resp[128];
- if (up)
- {
- if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
- me, &iface))
- {
- cache_iface(this, child_sa->get_reqid(child_sa), iface);
- }
- else
- {
- iface = NULL;
+ if (fgets(resp, sizeof(resp), shell) == NULL)
+ {
+ if (ferror(shell))
+ {
+ DBG1(DBG_CHD, "error reading from updown script");
+ }
+ break;
+ }
+ else
+ {
+ char *e = resp + strlen(resp);
+ if (e > resp && e[-1] == '\n')
+ {
+ e[-1] = '\0';
+ }
+ DBG1(DBG_CHD, "updown: %s", resp);
+ }
}
+ fclose(shell);
}
else
{
- iface = uncache_iface(this, child_sa->get_reqid(child_sa));
+ close(out);
}
+ process->wait(process, NULL);
+ }
+ free(iface);
+ free_env(envp);
+}
- dns = make_dns_vars(this, ike_sa);
-
- /* check for IPComp */
- use_ipcomp = child_sa->get_ipcomp(child_sa) != IPCOMP_NONE;
-
- /* determine IPv4/IPv6 and client/host situation */
- is_host = my_ts->is_host(my_ts, me);
- is_ipv6 = is_host ? (me->get_family(me) == AF_INET6) :
- (my_ts->get_type(my_ts) == TS_IPV6_ADDR_RANGE);
-
- /* build the command with all env variables.
- */
- snprintf(command, sizeof(command),
- "2>&1 "
- "PLUTO_VERSION='1.1' "
- "PLUTO_VERB='%s%s%s' "
- "PLUTO_CONNECTION='%s' "
- "PLUTO_INTERFACE='%s' "
- "PLUTO_REQID='%u' "
- "PLUTO_PROTO='%s' "
- "PLUTO_UNIQUEID='%u' "
- "PLUTO_ME='%H' "
- "PLUTO_MY_ID='%Y' "
- "PLUTO_MY_CLIENT='%+H/%u' "
- "PLUTO_MY_PORT='%u' "
- "PLUTO_MY_PROTOCOL='%u' "
- "PLUTO_PEER='%H' "
- "PLUTO_PEER_ID='%Y' "
- "PLUTO_PEER_CLIENT='%+H/%u' "
- "PLUTO_PEER_PORT='%u' "
- "PLUTO_PEER_PROTOCOL='%u' "
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s"
- "%s",
- up ? "up" : "down",
- is_host ? "-host" : "-client",
- is_ipv6 ? "-v6" : "",
- config->get_name(config),
- iface ? iface : "unknown",
- child_sa->get_reqid(child_sa),
- child_sa->get_protocol(child_sa) == PROTO_ESP ? "esp" : "ah",
- ike_sa->get_unique_id(ike_sa),
- me, ike_sa->get_my_id(ike_sa),
- my_client, my_client_mask,
- get_port(my_ts, other_ts, TRUE),
- my_ts->get_protocol(my_ts),
- other, ike_sa->get_other_id(ike_sa),
- other_client, other_client_mask,
- get_port(my_ts, other_ts, FALSE),
- other_ts->get_protocol(other_ts),
- xauth,
- virtual_ip,
- mark_in,
- mark_out,
- udp_enc,
- use_ipcomp ? "PLUTO_IPCOMP='1' " : "",
- config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
- dns,
- script);
- my_client->destroy(my_client);
- other_client->destroy(other_client);
- free(virtual_ip);
- free(mark_in);
- free(mark_out);
- free(udp_enc);
- free(dns);
- free(iface);
- free(xauth);
-
- DBG3(DBG_CHD, "running updown script: %s", command);
- shell = popen(command, "r");
-
- if (shell == NULL)
- {
- DBG1(DBG_CHD, "could not execute updown script '%s'", script);
- return TRUE;
- }
+METHOD(listener_t, child_updown, bool,
+ private_updown_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+ bool up)
+{
+ traffic_selector_t *my_ts, *other_ts;
+ enumerator_t *enumerator;
+ child_cfg_t *config;
- while (TRUE)
+ config = child_sa->get_config(child_sa);
+ if (config->get_updown(config))
+ {
+ enumerator = child_sa->create_policy_enumerator(child_sa);
+ while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
- char resp[128];
-
- if (fgets(resp, sizeof(resp), shell) == NULL)
- {
- if (ferror(shell))
- {
- DBG1(DBG_CHD, "error reading output from updown script");
- }
- break;
- }
- else
- {
- char *e = resp + strlen(resp);
- if (e > resp && e[-1] == '\n')
- { /* trim trailing '\n' */
- e[-1] = '\0';
- }
- DBG1(DBG_CHD, "updown: %s", resp);
- }
+ invoke_once(this, ike_sa, child_sa, config, up, my_ts, other_ts);
}
- pclose(shell);
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
return TRUE;
}
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
index 7e459c58d..da71de394 100644
--- a/src/libcharon/plugins/vici/Makefile.am
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -67,3 +67,10 @@ vici_tests_LDFLAGS = @COVERAGE_LDFLAGS@
vici_tests_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libstrongswan/tests/libtest.la
+
+
+SUBDIRS =
+
+if USE_RUBY_GEMS
+SUBDIRS += ruby
+endif
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
index e0a6a1b5d..34546b905 100644
--- a/src/libcharon/plugins/vici/Makefile.in
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -80,6 +80,7 @@ build_triplet = @build@
host_triplet = @host@
TESTS = vici_tests$(EXEEXT)
check_PROGRAMS = $(am__EXEEXT_1)
+@USE_RUBY_GEMS_TRUE@am__append_1 = ruby
subdir = src/libcharon/plugins/vici
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp
@@ -206,11 +207,27 @@ SOURCES = $(libstrongswan_vici_la_SOURCES) $(libvici_la_SOURCES) \
$(vici_tests_SOURCES)
DIST_SOURCES = $(libstrongswan_vici_la_SOURCES) $(libvici_la_SOURCES) \
$(vici_tests_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
@@ -252,7 +269,33 @@ am__tty_colors = { \
std=''; \
fi; \
}
+DIST_SUBDIRS = ruby
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
@@ -284,6 +327,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -344,6 +388,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -409,6 +454,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -456,6 +503,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
@@ -520,7 +571,8 @@ vici_tests_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libstrongswan/tests/libtest.la
-all: all-am
+SUBDIRS = $(am__append_1)
+all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
@@ -869,14 +921,61 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
+tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
@@ -889,7 +988,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$$unique; \
fi; \
fi
-ctags: ctags-am
+ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
@@ -902,7 +1001,7 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
+cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
@@ -1044,24 +1143,50 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
+check: check-recursive
all-am: Makefile $(LTLIBRARIES)
-installdirs:
+installdirs: installdirs-recursive
+installdirs-am:
for dir in "$(DESTDIR)$(ipseclibdir)" "$(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: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@@ -1085,96 +1210,97 @@ distclean-generic:
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: clean-recursive
clean-am: clean-checkPROGRAMS clean-generic clean-ipseclibLTLIBRARIES \
clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
mostlyclean-am
-distclean: distclean-am
+distclean: distclean-recursive
-rm -rf ./$(DEPDIR) suites/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
html-am:
-info: info-am
+info: info-recursive
info-am:
install-data-am: install-ipseclibLTLIBRARIES install-pluginLTLIBRARIES
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
-install-html: install-html-am
+install-html: install-html-recursive
install-html-am:
-install-info: install-info-am
+install-info: install-info-recursive
install-info-am:
install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
install-pdf-am:
-install-ps: install-ps-am
+install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
-maintainer-clean: maintainer-clean-am
+maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR) suites/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
uninstall-am: uninstall-ipseclibLTLIBRARIES \
uninstall-pluginLTLIBRARIES
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
- clean-checkPROGRAMS clean-generic clean-ipseclibLTLIBRARIES \
- clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
- cscopelist-am ctags ctags-am distclean distclean-compile \
- distclean-generic distclean-libtool distclean-tags distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-data install-data-am install-dvi install-dvi-am \
- install-exec install-exec-am install-html install-html-am \
- install-info install-info-am install-ipseclibLTLIBRARIES \
- install-man install-pdf install-pdf-am \
- install-pluginLTLIBRARIES install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+.MAKE: $(am__recursive_targets) check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-TESTS check-am clean clean-checkPROGRAMS clean-generic \
+ clean-ipseclibLTLIBRARIES clean-libtool \
+ clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-ipseclibLTLIBRARIES install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am \
uninstall-ipseclibLTLIBRARIES uninstall-pluginLTLIBRARIES
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index aeabbbd4d..272491052 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -84,12 +84,12 @@ The message encoding consists of a sequence of elements. Each element starts
with the element type, optionally followed by an element name and/or an element
value. Currently the following message element types are defined:
-* _SECTION_START = 0_: Begin a new section having a name
-* _SECTION_END = 1_: End a previously started section
-* _KEY_VALUE = 2_: Define a value for a named key in the current section
-* _LIST_START = 3_: Begin a named list for list items
-* _LIST_ITEM = 4_: Define an unnamed item value in the current list
-* _LIST_END = 5_: End a previously started list
+* _SECTION_START = 1_: Begin a new section having a name
+* _SECTION_END = 2_: End a previously started section
+* _KEY_VALUE = 3_: Define a value for a named key in the current section
+* _LIST_START = 4_: Begin a named list for list items
+* _LIST_ITEM = 5_: Define an unnamed item value in the current list
+* _LIST_END = 6_: End a previously started list
Types are encoded as 8-bit values. Types having a name (SECTION_START,
KEY_VALUE and LIST_START) have an ASCII string following the type, which itself
@@ -103,7 +103,8 @@ the length field itself.
The interpretation of any value is not defined by the message format; it can
take arbitrary blobs. The application may specify types for specific keys, such
-as strings or integer representations.
+as strings or integer representations. The vici plugin currently uses
+non-null terminated strings as values only; numbers get encoded as strings.
### Sections ###
@@ -165,6 +166,513 @@ the following C array:
1,
};
+## Client-initiated commands ##
+
+Based on the packet layer, VICI implements commands requested by the client
+and responded to by the server using named _CMD_REQUEST_ and _CMD_RESPONSE_
+packets wrapping messages. The request message may contain command arguments,
+the response message the reply.
+
+Some commands use response streaming, that is, a request triggers a series of
+events to consecutively stream data to the client before the response message
+completes the stream. A client must register for the appropriate event to
+receive the stream, and unregister after the response has been received.
+
+The following client issued commands with the appropriate command input and
+output messages are currently defined:
+
+### version() ###
+
+Returns daemon and system specific version information.
+
+ {} => {
+ daemon = <IKE daemon name>
+ version = <strongSwan version>
+ sysname = <operating system name>
+ release = <operating system release>
+ machine = <hardware identifier>
+ }
+
+### stats() ###
+
+Returns IKE daemon statistics and load information.
+
+ {} => {
+ uptime = {
+ running = <relative uptime in human-readable form>
+ since = <absolute startup time>
+ }
+ workers = {
+ total = <total number of worker threads>
+ idle = <worker threads currently idle>
+ active = {
+ critical = <threads processing "critical" priority jobs>
+ high = <threads processing "high" priority jobs>
+ medium = <threads processing "medium" priority jobs>
+ low = <threads processing "low" priority jobs>
+ }
+ }
+ queues = {
+ critical = <jobs queued with "critical" priority>
+ high = <jobs queued with "high" priority>
+ medium = <jobs queued with "medium" priority>
+ low = <jobs queued with "low" priority>
+ }
+ scheduled = <number of jobs scheduled for timed execution>
+ ikesas = {
+ total = <total number of IKE_SAs active>
+ half-open = <number of IKE_SAs in half-open state>
+ }
+ plugins = [
+ <names of loaded plugins>
+ ]
+ mem = { # available if built with leak-detective or on Windows
+ total = <total heap memory usage in bytes>
+ allocs = <total heap allocation blocks>
+ <heap-name>* = { # on Windows only
+ total = <heap memory usage in bytes by this heap>
+ allocs = <allocated blocks for this heap>
+ }
+ }
+ mallinfo = { # available with mallinfo() support
+ sbrk = <non-mmaped space available>
+ mmap = <mmaped space available>
+ used = <total number of bytes used>
+ free = <available but unused bytes>
+ }
+ }
+
+### reload-settings() ###
+
+Reloads _strongswan.conf_ settings and all plugins supporting configuration
+reload.
+
+ {} => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### initiate() ###
+
+Initiates an SA while streaming _control-log_ events.
+
+ {
+ child = <CHILD_SA configuration name to initiate>
+ timeout = <timeout in seconds before returning>
+ loglevel = <loglevel to issue "control-log" events for>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure or timeout>
+ }
+
+### terminate() ###
+
+Terminates an SA while streaming _control-log_ events.
+
+ {
+ child = <terminate a CHILD_SA by configuration name>
+ ike = <terminate an IKE_SA by configuration name>
+ child_id = <terminate a CHILD_SA by its reqid>
+ ike_id = <terminate an IKE_SA by its unique id>
+ timeout = <timeout in seconds before returning>
+ loglevel = <loglevel to issue "control-log" events for>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure or timeout>
+ }
+
+### install() ###
+
+Install a trap, drop or bypass policy defined by a CHILD_SA config.
+
+ {
+ child = <CHILD_SA configuration name to install>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### uninstall() ###
+
+Uninstall a trap, drop or bypass policy defined by a CHILD_SA config.
+
+ {
+ child = <CHILD_SA configuration name to install>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### list-sas() ###
+
+Lists currently active IKE_SAs and associated CHILD_SAs by streaming _list-sa_
+events.
+
+ {
+ noblock = <use non-blocking mode if key is set>
+ ike = <filter listed IKE_SAs by its name>
+ ike_id = <filter listed IKE_SA by its unique id>
+ } => {
+ # completes after streaming list-sa events
+ }
+
+### list-policies() ###
+
+List currently installed trap, drop and bypass policies by streaming
+_list-policy_ events.
+
+ {
+ drop = <set to yes to list drop policies>
+ pass = <set to yes to list bypass policies>
+ trap = <set to yes to list trap policies>
+ child = <filter by CHILD_SA configuration name>
+ } => {
+ # completes after streaming list-sa events
+ }
+
+### list-conns() ###
+
+List currently loaded connections by streaming _list-conn_ events. This
+call includes all connections known by the daemon, not only those loaded
+over vici.
+
+ {
+ ike = <list connections matching a given configuration name only>
+ } => {
+ # completes after streaming list-conn events
+ }
+
+### get-conns() ###
+
+Return a list of connection names loaded exclusively over vici, not including
+connections found in other backends.
+
+ {} => {
+ conns = [
+ <list of connection names>
+ ]
+ }
+
+### list-certs() ###
+
+List currently loaded certificates by streaming _list-cert_ events. This
+call includes all certificates known by the daemon, not only those loaded
+over vici.
+
+ {
+ type = <certificate type to filter for, or ANY>
+ subject = <set to list only certificates having subject>
+ } => {
+ # completes after streaming list-cert events
+ }
+
+### load-conn() ###
+
+Load a single connection definition into the daemon. An existing connection
+with the same name gets updated or replaced.
+
+ {
+ <IKE_SA config name> = {
+ # IKE configuration parameters with authentication and CHILD_SA
+ # subsections. Refer to swanctl.conf(5) for details.
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+ }
+
+### unload-conn() ###
+
+Unload a previously loaded connection definition by name.
+
+ {
+ name = <IKE_SA config name>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### load-cert() ###
+
+Load a certificate into the daemon.
+
+ {
+ type = <certificate type, X509|X509CA|X509AA|X509CRL|X509AC>
+ data = <PEM or DER encoded certificate data>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### load-key() ###
+
+Load a private key into the daemon.
+
+ {
+ type = <private key type, RSA|ECDSA>
+ data = <PEM or DER encoded key data>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### load-shared() ###
+
+Load a shared IKE PSK, EAP or XAuth secret into the daemon.
+
+ {
+ type = <private key type, IKE|EAP|XAUTH>
+ data = <raw shared key data>
+ owners = [
+ <list of shared key owner identities>
+ ]
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### clear-creds() ###
+
+Clear all loaded certificate, private key and shared key credentials. This
+affects only credentials loaded over vici, but additionally flushes the
+credential cache.
+
+ {} => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### load-pool() ###
+
+Load an in-memory virtual IP and configuration attribute pool. Existing
+pools with the same name get updated, if possible.
+
+ {
+ <pool name> = {
+ addrs = <subnet of virtual IP pool addresses>
+ <attribute type>* = [
+ # attribute type is one of address, dns, nbns, dhcp, netmask,
+ # server, subnet, split_include, split_exclude or a numerical
+ # attribute type identifier.
+ <list of attributes for type>
+ ]
+ }
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### unload-pool() ###
+
+Unload a previously loaded virtual IP and configuration attribute pool.
+Unloading fails for pools with leases currently online.
+
+ {
+ name = <virtual IP address pool to delete>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
+### get-pools() ###
+
+List the currently loaded pools.
+
+ {} => {
+ <pool name>* = {
+ base = <virtual IP pool base address>
+ size = <total number of addresses in the pool>
+ online = <number of leases online>
+ offline = <number of leases offline>
+ }
+ }
+
+## Server-issued events ##
+
+Based on the packet layer, the vici plugin raises event messages using named
+EVENT packets wrapping messages. The message contains event details.
+
+### log ###
+
+The _log_ event is issued to registered clients for each debug log message.
+This event is not associated with a command.
+
+ {
+ group = <subsystem identifier for debug message>
+ level = <log level, 0-4>
+ thread = <numerical thread identifier issuing the log message>
+ ikesa-name = <name of IKE_SA, if log is associated with any>
+ ikesa-uniqued = <unique identifier of IKE_A, if log associated with any>
+ msg = <log message text>
+ }
+
+### control-log ###
+
+The _control-log_ event is issued for log events during active _initiate_ or
+_terminate_ commands. It is issued only to clients currently having such
+a command active.
+
+ {
+ group = <subsystem identifier for debug message>
+ level = <log level, 0-4>
+ ikesa-name = <name of IKE_SA, if log associated with any>
+ ikesa-uniqued = <unique identifier of IKE_A, if log associated with any>
+ msg = <log message text>
+ }
+
+### list-sa ###
+
+The _list-sa_ event is issued to stream IKE_SAs during an active _list-sas_
+command.
+
+ {
+ <IKE_SA config name> = {
+ uniqueid = <IKE_SA unique identifier>
+ version = <IKE version, 1 or 2>
+ state = <IKE_SA state name>
+ local-host = <local IKE endpoint address>
+ local-id = <local IKE identity>
+ remote-host = <remote IKE endpoint address>
+ remote-id = <remote IKE identity>
+ remote-xauth-id = <remote XAuth identity, if XAuth-authenticated>
+ remote-eap-id = <remote EAP identity, if EAP-authenticated>
+ initiator = <yes, if initiator of IKE_SA>
+ initiator-spi = <hex encoded initiator SPI / cookie>
+ responder-spi = <hex encoded responder SPI / cookie>
+ encr-alg = <IKE encryption algorithm string>
+ encr-keysize = <key size for encr-alg, if applicable>
+ integ-alg = <IKE integrity algorithm string>
+ integ-keysize = <key size for encr-alg, if applicable>
+ prf-alg = <IKE pseudo random function string>
+ dh-group = <IKE Diffie-Hellman group string>
+ established = <seconds the IKE_SA has been established>
+ rekey-time = <seconds before IKE_SA gets rekeyed>
+ reauth-time = <seconds before IKE_SA gets re-authenticated>
+ tasks-queued = [
+ <list of currently queued tasks for execution>
+ ]
+ tasks-active = [
+ <list of tasks currently initiating actively>
+ ]
+ tasks-passive = [
+ <list of tasks currently handling passively>
+ ]
+ child-sas = {
+ <child-sa-name>* = {
+ reqid = <reqid of CHILD_SA>
+ state = <state string of CHILD_SA>
+ mode = <IPsec mode, tunnel|transport|beet>
+ protocol = <IPsec protocol AH|ESP>
+ encap = <yes if using UDP encapsulation>
+ spi-in = <hex encoded inbound SPI>
+ spi-out = <hex encoded outbound SPI>
+ cpi-in = <hex encoded inbound CPI, if using compression>
+ cpi-out = <hex encoded outbound CPI, if using compression>
+ encr-alg = <ESP encryption algorithm name, if any>
+ encr-keysize = <ESP encryption key size, if applicable>
+ integ-alg = <ESP or AH integrity algorithm name, if any>
+ integ-keysize = <ESP or AH integrity key size, if applicable>
+ prf-alg = <CHILD_SA pseudo random function name>
+ dh-group = <CHILD_SA PFS rekeying DH group name, if any>
+ esn = <1 if using extended sequence numbers>
+ bytes-in = <number of input bytes processed>
+ packets-in = <number of input packets processed>
+ use-in = <seconds since last inbound packet, if any>
+ bytes-out = <number of output bytes processed>
+ packets-out = <number of output packets processed>
+ use-out = <seconds since last outbound packet, if any>
+ rekey-time = <seconds before CHILD_SA gets rekeyed>
+ life-time = <seconds before CHILD_SA expires>
+ install-time = <seconds the CHILD_SA has been installed>
+ local-ts = [
+ <list of local traffic selectors>
+ ]
+ remote-ts = [
+ <list of remote traffic selectors>
+ ]
+ }
+ }
+ }
+ }
+
+### list-policy ###
+
+The _list-policy_ event is issued to stream installed policies during an active
+_list-policies_ command.
+
+ {
+ <child-sa-config-name> = {
+ mode = <policy mode, tunnel|transport|pass|drop>
+ local-ts = [
+ <list of local traffic selectors>
+ ]
+ remote-ts = [
+ <list of remote traffic selectors>
+ ]
+ }
+ }
+
+### list-conn ###
+
+The _list-conn_ event is issued to stream loaded connection during an active
+_list-conns_ command.
+
+ {
+ <IKE_SA connection name> = {
+ local_addrs = [
+ <list of valid local IKE endpoint addresses>
+ ]
+ remote_addrs = [
+ <list of valid remote IKE endpoint addresses>
+ ]
+ version = <IKE version as string, IKEv1|IKEv2 or 0 for any>
+
+ local*, remote* = { # multiple local and remote auth sections
+ class = <authentication type>
+ eap-type = <EAP type to authenticate if when using EAP>
+ eap-vendor = <EAP vendor for type, if any>
+ xauth = <xauth backend name>
+ revocation = <revocation policy>
+ id = <IKE identity>
+ aaa_id = <AAA authentication backend identity>
+ eap_id = <EAP identity for authentication>
+ xauth_id = <XAuth username for authentication>
+ groups = [
+ <group membership required to use connection>
+ ]
+ certs = [
+ <certificates allowed for authentication>
+ ]
+ cacerts = [
+ <CA certificates allowed for authentication>
+ ]
+ }
+ children = {
+ <CHILD_SA config name>* = {
+ mode = <IPsec mode>
+ local-ts = [
+ <list of local traffic selectors>
+ ]
+ remote-ts = [
+ <list of remote traffic selectors>
+ ]
+ }
+ }
+ }
+ }
+
+### list-cert ###
+
+The _list-cert_ event is issued to stream loaded certificates during an active
+_list-certs_ command.
+
+ {
+ type = <certificate type>
+ has_privkey = <set if a private key for the certificate is available>
+ data = <ASN1 encoded certificate data>
+ }
+
+
# libvici C client library #
libvici is the reference implementation of a C client library implementing
@@ -172,5 +680,177 @@ the vici protocol. It builds upon libstrongswan, but provides a stable API
to implement client applications in the C programming language. libvici uses
the libstrongswan thread pool to deliver event messages asynchronously.
-More information about the libvici API is available in the libvici.h header
-file.
+## Connecting to the daemon ##
+
+This example shows how to connect to the daemon using the default URI, and
+then perform proper cleanup:
+
+ #include <stdio.h>
+ #include <errno.h>
+ #include <string.h>
+
+ #include <libvici.h>
+
+ int main(int argc, char *argv[])
+ {
+ vici_conn_t *conn;
+ int ret = 0;
+
+ vici_init();
+ conn = vici_connect(NULL);
+ if (conn)
+ {
+ /* do stuff */
+ vici_disconnect(conn);
+ }
+ else
+ {
+ ret = errno;
+ fprintf(stderr, "connecting failed: %s\n", strerror(errno));
+ }
+ vici_deinit();
+ return ret;
+ }
+
+## A simple client request ##
+
+In the following example, a simple _version_ request is issued to the daemon
+and the result is printed:
+
+ int get_version(vici_conn_t *conn)
+ {
+ vici_req_t *req;
+ vici_res_t *res;
+ int ret = 0;
+
+ req = vici_begin("version");
+ res = vici_submit(req, conn);
+ if (res)
+ {
+ printf("%s %s (%s, %s, %s)\n",
+ vici_find_str(res, "", "daemon"),
+ vici_find_str(res, "", "version"),
+ vici_find_str(res, "", "sysname"),
+ vici_find_str(res, "", "release"),
+ vici_find_str(res, "", "machine"));
+ vici_free_res(res);
+ }
+ else
+ {
+ ret = errno;
+ fprintf(stderr, "version request failed: %s\n", strerror(errno));
+ }
+ return ret;
+ }
+
+## A request with event streaming and callback parsing ##
+
+In this more advanced example, the _list-conns_ command is used to stream
+loaded connections with the _list-conn_ event. The event message is parsed
+with a simple callback to print the connection name:
+
+ int conn_cb(void *null, vici_res_t *res, char *name)
+ {
+ printf("%s\n", name);
+ return 0;
+ }
+
+ void list_cb(void *null, char *name, vici_res_t *res)
+ {
+ if (vici_parse_cb(res, conn_cb, NULL, NULL, NULL) != 0)
+ {
+ fprintf(stderr, "parsing failed: %s\n", strerror(errno));
+ }
+ }
+
+ int list_conns(vici_conn_t *conn)
+ {
+ vici_req_t *req;
+ vici_res_t *res;
+ int ret = 0;
+
+ if (vici_register(conn, "list-conn", list_cb, NULL) == 0)
+ {
+ req = vici_begin("list-conns");
+ res = vici_submit(req, conn);
+ if (res)
+ {
+ vici_free_res(res);
+ }
+ else
+ {
+ ret = errno;
+ fprintf(stderr, "request failed: %s\n", strerror(errno));
+ }
+ vici_register(conn, "list-conn", NULL, NULL);
+ }
+ else
+ {
+ ret = errno;
+ fprintf(stderr, "registration failed: %s\n", strerror(errno));
+ }
+ return ret;
+ }
+
+## API documentation ##
+
+More information about the libvici API is available in the _libvici.h_ header
+file or the generated Doxygen documentation.
+
+# vici ruby gem #
+
+The _vici ruby gem_ is a pure ruby implementation of the VICI protocol to
+implement client applications. It is provided in the _ruby_ subdirectory, and
+gets built and installed if strongSwan has been _./configure_'d with
+_--enable-vici_ and _--enable-ruby-gems_.
+
+The _Connection_ class from the _Vici_ module provides the high level interface,
+the underlying classes are usually not required to build ruby applications
+using VICI. The _Connection_ class provides methods for the supported VICI
+commands and an event listening mechanism.
+
+To represent the VICI message data tree, the gem converts the binary encoding
+to ruby data types. The _Connection_ class takes and returns ruby objects for
+the exchanged message data:
+ * Sections get encoded as Hash, containing other sections as Hash, or
+ * Key/Values, where the values are Strings as Hash values
+ * Lists get encoded as Arrays with String values
+Non-String values that are not a Hash nor an Array get converted with .to_s
+during encoding.
+
+## Connecting to the daemon ##
+
+To create a connection to the daemon, a socket must be passed to the
+_Connection_ constructor. There is no default, but on Unix systems usually
+a Unix socket over _/var/run/charon.vici_ is used:
+
+ require "vici"
+ require "socket"
+
+ v = Vici::Connection.new(UNIXSocket.new("/var/run/charon.vici"))
+
+## A simple client request ##
+
+An example to print the daemon version information is as simple as:
+
+ x = v.version
+ puts "%s %s (%s, %s, %s)" % [
+ x["daemon"], x["version"], x["sysname"], x["release"], x["machine"]
+ ]
+
+## A request with closure invocation ##
+
+The _Connection_ class takes care of event streaming by invoking a closure
+for each event. The following example lists all loaded connections using the
+_list-conns_ command and implicitly the _list-conn_ event:
+
+ v.list_conns { |conn|
+ conn.each { |key, value|
+ puts key
+ }
+ }
+
+## API documentation ##
+
+For more details about the ruby gem refer to the comments in the gem source
+code or the generated documentation.
diff --git a/src/libcharon/plugins/vici/libvici.c b/src/libcharon/plugins/vici/libvici.c
index a2cbb3082..c0205ccb6 100644
--- a/src/libcharon/plugins/vici/libvici.c
+++ b/src/libcharon/plugins/vici/libvici.c
@@ -438,7 +438,7 @@ void vici_free_req(vici_req_t *req)
free(req);
}
-int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out)
+int vici_dump(vici_res_t *res, char *label, int pretty, FILE *out)
{
if (res->message->dump(res->message, label, pretty, out))
{
@@ -754,11 +754,14 @@ void vici_init()
library_init(NULL, "vici");
if (lib->processor->get_total_threads(lib->processor) < 4)
{
+ dbg_default_set_level(0);
lib->processor->set_threads(lib->processor, 4);
+ dbg_default_set_level(1);
}
}
void vici_deinit()
{
+ lib->processor->cancel(lib->processor);
library_deinit();
}
diff --git a/src/libcharon/plugins/vici/libvici.h b/src/libcharon/plugins/vici/libvici.h
index 58595d8cc..641370efd 100644
--- a/src/libcharon/plugins/vici/libvici.h
+++ b/src/libcharon/plugins/vici/libvici.h
@@ -75,8 +75,6 @@
#include <stdio.h>
-#include <utils/utils.h>
-
/**
* Opaque vici connection contex.
*/
@@ -284,7 +282,7 @@ void vici_free_req(vici_req_t *req);
* @param out FILE to dump to
* @return 0 if dumped complete message, 1 on error
*/
-int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out);
+int vici_dump(vici_res_t *res, char *label, int pretty, FILE *out);
/**
* Parse next element from a vici response message.
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.am b/src/libcharon/plugins/vici/ruby/Makefile.am
new file mode 100644
index 000000000..ce38e1c3d
--- /dev/null
+++ b/src/libcharon/plugins/vici/ruby/Makefile.am
@@ -0,0 +1,22 @@
+EXTRA_DIST = vici.gemspec.in lib/vici.rb
+
+vici.gemspec: $(srcdir)/vici.gemspec.in
+ $(AM_V_GEN) sed \
+ -e "s:@GEM_VERSION@:$(PACKAGE_VERSION):" \
+ $(srcdir)/vici.gemspec.in > $@
+
+vici-$(PACKAGE_VERSION).gem: vici.gemspec
+ $(GEM) build vici.gemspec
+
+all-local: vici-$(PACKAGE_VERSION).gem
+
+clean-local:
+ rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
+
+install-data-local: vici-$(PACKAGE_VERSION).gem
+ $(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ vici-$(PACKAGE_VERSION).gem
+
+uninstall-local:
+ $(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ --version $(PACKAGE_VERSION) vici
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
new file mode 100644
index 000000000..c8a8c11fb
--- /dev/null
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -0,0 +1,556 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libcharon/plugins/vici/ruby
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+EXTRA_DIST = vici.gemspec.in lib/vici.rb
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libcharon/plugins/vici/ruby/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libcharon/plugins/vici/ruby/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+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 all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+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 -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ clean-libtool clean-local cscopelist-am ctags-am distclean \
+ distclean-generic distclean-libtool distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am uninstall-local
+
+
+vici.gemspec: $(srcdir)/vici.gemspec.in
+ $(AM_V_GEN) sed \
+ -e "s:@GEM_VERSION@:$(PACKAGE_VERSION):" \
+ $(srcdir)/vici.gemspec.in > $@
+
+vici-$(PACKAGE_VERSION).gem: vici.gemspec
+ $(GEM) build vici.gemspec
+
+all-local: vici-$(PACKAGE_VERSION).gem
+
+clean-local:
+ rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
+
+install-data-local: vici-$(PACKAGE_VERSION).gem
+ $(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ vici-$(PACKAGE_VERSION).gem
+
+uninstall-local:
+ $(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ --version $(PACKAGE_VERSION) vici
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb
new file mode 100644
index 000000000..e8a9ddca9
--- /dev/null
+++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb
@@ -0,0 +1,569 @@
+##
+# The Vici module implements a native ruby client side library for the
+# strongSwan VICI protocol. The Connection class provides a high-level
+# interface to issue requests or listen for events.
+#
+# Copyright (C) 2014 Martin Willi
+# Copyright (C) 2014 revosec AG
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+module Vici
+
+ ##
+ # Vici specific exception all others inherit from
+ class Error < StandardError
+ end
+
+ ##
+ # Error while parsing a vici message from the daemon
+ class ParseError < Error
+ end
+
+ ##
+ # Error while encoding a vici message from ruby data structures
+ class EncodeError < Error
+ end
+
+ ##
+ # Error while exchanging messages over the vici Transport layer
+ class TransportError < Error
+ end
+
+ ##
+ # Generic vici command execution error
+ class CommandError < Error
+ end
+
+ ##
+ # Error if an issued vici command is unknown by the daemon
+ class CommandUnknownError < CommandError
+ end
+
+ ##
+ # Error if a command failed to execute in the daemon
+ class CommandExecError < CommandError
+ end
+
+ ##
+ # Generic vici event handling error
+ class EventError < Error
+ end
+
+ ##
+ # Tried to register to / unregister from an unknown vici event
+ class EventUnknownError < EventError
+ end
+
+ ##
+ # Exception to raise from an event listening closure to stop listening
+ class StopEventListening < Exception
+ end
+
+
+ ##
+ # The Message class provides the low level encoding and decoding of vici
+ # protocol messages. Directly using this class is usually not required.
+ class Message
+
+ SECTION_START = 1
+ SECTION_END = 2
+ KEY_VALUE = 3
+ LIST_START = 4
+ LIST_ITEM = 5
+ LIST_END = 6
+
+ def initialize(data = "")
+ if data == nil
+ @root = Hash.new()
+ elsif data.is_a?(Hash)
+ @root = data
+ else
+ @encoded = data
+ end
+ end
+
+ ##
+ # Get the raw byte encoding of an on-the-wire message
+ def encoding
+ if @encoded == nil
+ @encoded = encode(@root)
+ end
+ @encoded
+ end
+
+ ##
+ # Get the root element of the parsed ruby data structures
+ def root
+ if @root == nil
+ @root = parse(@encoded)
+ end
+ @root
+ end
+
+ private
+
+ def encode_name(name)
+ [name.length].pack("c") << name
+ end
+
+ def encode_value(value)
+ if value.class != String
+ value = value.to_s
+ end
+ [value.length].pack("n") << value
+ end
+
+ def encode_kv(encoding, key, value)
+ encoding << KEY_VALUE << encode_name(key) << encode_value(value)
+ end
+
+ def encode_section(encoding, key, value)
+ encoding << SECTION_START << encode_name(key)
+ encoding << encode(value) << SECTION_END
+ end
+
+ def encode_list(encoding, key, value)
+ encoding << LIST_START << encode_name(key)
+ value.each do |item|
+ encoding << LIST_ITEM << encode_value(item)
+ end
+ encoding << LIST_END
+ end
+
+ def encode(node)
+ encoding = ""
+ node.each do |key, value|
+ case value.class
+ when String, Fixnum, true, false
+ encoding = encode_kv(encoding, key, value)
+ else
+ if value.is_a?(Hash)
+ encoding = encode_section(encoding, key, value)
+ elsif value.is_a?(Array)
+ encoding = encode_list(encoding, key, value)
+ else
+ encoding = encode_kv(encoding, key, value)
+ end
+ end
+ end
+ encoding
+ end
+
+ def parse_name(encoding)
+ len = encoding.unpack("c")[0]
+ name = encoding[1, len]
+ return encoding[(1 + len)..-1], name
+ end
+
+ def parse_value(encoding)
+ len = encoding.unpack("n")[0]
+ value = encoding[2, len]
+ return encoding[(2 + len)..-1], value
+ end
+
+ def parse(encoding)
+ stack = [Hash.new]
+ list = nil
+ while encoding.length != 0 do
+ type = encoding.unpack("c")[0]
+ encoding = encoding[1..-1]
+ case type
+ when SECTION_START
+ encoding, name = parse_name(encoding)
+ stack.push(stack[-1][name] = Hash.new)
+ when SECTION_END
+ if stack.length() == 1
+ raise ParseError, "unexpected section end"
+ end
+ stack.pop()
+ when KEY_VALUE
+ encoding, name = parse_name(encoding)
+ encoding, value = parse_value(encoding)
+ stack[-1][name] = value
+ when LIST_START
+ encoding, name = parse_name(encoding)
+ stack[-1][name] = []
+ list = name
+ when LIST_ITEM
+ raise ParseError, "unexpected list item" if list == nil
+ encoding, value = parse_value(encoding)
+ stack[-1][list].push(value)
+ when LIST_END
+ raise ParseError, "unexpected list end" if list == nil
+ list = nil
+ else
+ raise ParseError, "invalid type: #{type}"
+ end
+ end
+ if stack.length() > 1
+ raise ParseError, "unexpected message end"
+ end
+ stack[0]
+ end
+ end
+
+
+ ##
+ # The Transport class implements to low level segmentation of packets
+ # to the underlying transport stream. Directly using this class is usually
+ # not required.
+ class Transport
+
+ CMD_REQUEST = 0
+ CMD_RESPONSE = 1
+ CMD_UNKNOWN = 2
+ EVENT_REGISTER = 3
+ EVENT_UNREGISTER = 4
+ EVENT_CONFIRM = 5
+ EVENT_UNKNOWN = 6
+ EVENT = 7
+
+ ##
+ # Create a transport layer using a provided socket for communication.
+ def initialize(socket)
+ @socket = socket
+ @events = Hash.new
+ end
+
+ ##
+ # Write a packet prefixed by its length over the transport socket. Type
+ # specifies the message, the optional label and message get appended.
+ def write(type, label, message)
+ encoding = ""
+ if label
+ encoding << label.length << label
+ end
+ if message
+ encoding << message.encoding
+ end
+ @socket.send([encoding.length + 1, type].pack("Nc") + encoding, 0)
+ end
+
+ ##
+ # Read a packet from the transport socket. Returns the packet type, and
+ # if available in the packet a label and the contained message.
+ def read
+ len = @socket.recv(4).unpack("N")[0]
+ encoding = @socket.recv(len)
+ type = encoding.unpack("c")[0]
+ len = 1
+ case type
+ when CMD_REQUEST, EVENT_REGISTER, EVENT_UNREGISTER, EVENT
+ label = encoding[2, encoding[1].unpack("c")[0]]
+ len += label.length + 1
+ when CMD_RESPONSE, CMD_UNKNOWN, EVENT_CONFIRM, EVENT_UNKNOWN
+ label = nil
+ else
+ raise TransportError, "invalid message: #{type}"
+ end
+ if encoding.length == len
+ return type, label, Message.new
+ end
+ return type, label, Message.new(encoding[len..-1])
+ end
+
+ def dispatch_event(name, message)
+ @events[name].each do |handler|
+ handler.call(name, message)
+ end
+ end
+
+ def read_and_dispatch_event
+ type, label, message = read
+ p
+ if type == EVENT
+ dispatch_event(label, message)
+ else
+ raise TransportError, "unexpected message: #{type}"
+ end
+ end
+
+ def read_and_dispatch_events
+ loop do
+ type, label, message = read
+ if type == EVENT
+ dispatch_event(label, message)
+ else
+ return type, label, message
+ end
+ end
+ end
+
+ ##
+ # Send a command with a given name, and optionally a message. Returns
+ # the reply message on success.
+ def request(name, message = nil)
+ write(CMD_REQUEST, name, message)
+ type, label, message = read_and_dispatch_events
+ case type
+ when CMD_RESPONSE
+ return message
+ when CMD_UNKNOWN
+ raise CommandUnknownError, name
+ else
+ raise CommandError, "invalid response for #{name}"
+ end
+ end
+
+ ##
+ # Register a handler method for the given event name
+ def register(name, handler)
+ write(EVENT_REGISTER, name, nil)
+ type, label, message = read_and_dispatch_events
+ case type
+ when EVENT_CONFIRM
+ if @events.has_key?(name)
+ @events[name] += [handler]
+ else
+ @events[name] = [handler];
+ end
+ when EVENT_UNKNOWN
+ raise EventUnknownError, name
+ else
+ raise EventError, "invalid response for #{name} register"
+ end
+ end
+
+ ##
+ # Unregister a handler method for the given event name
+ def unregister(name, handler)
+ write(EVENT_UNREGISTER, name, nil)
+ type, label, message = read_and_dispatch_events
+ case type
+ when EVENT_CONFIRM
+ @events[name] -= [handler]
+ when EVENT_UNKNOWN
+ raise EventUnknownError, name
+ else
+ raise EventError, "invalid response for #{name} unregister"
+ end
+ end
+ end
+
+
+ ##
+ # The Connection class provides the high-level interface to monitor, configure
+ # and control the IKE daemon. It takes a connected stream-oriented Socket for
+ # the communication with the IKE daemon.
+ #
+ # This class takes and returns ruby objects for the exchanged message data.
+ # * Sections get encoded as Hash, containing other sections as Hash, or
+ # * Key/Values, where the values are Strings as Hash values
+ # * Lists get encoded as Arrays with String values
+ # Non-String values that are not a Hash nor an Array get converted with .to_s
+ # during encoding.
+ class Connection
+
+ def initialize(socket)
+ @transp = Transport.new(socket)
+ end
+
+ ##
+ # List matching loaded connections. The provided closure is invoked
+ # for each matching connection.
+ def list_conns(match = nil, &block)
+ call_with_event("list-conns", Message.new(match), "list-conn", &block)
+ end
+
+ ##
+ # List matching active SAs. The provided closure is invoked for each
+ # matching SA.
+ def list_sas(match = nil, &block)
+ call_with_event("list-sas", Message.new(match), "list-sa", &block)
+ end
+
+ ##
+ # List matching installed policies. The provided closure is invoked
+ # for each matching policy.
+ def list_policies(match, &block)
+ call_with_event("list-policies", Message.new(match), "list-policy",
+ &block)
+ end
+
+ ##
+ # List matching loaded certificates. The provided closure is invoked
+ # for each matching certificate definition.
+ def list_certs(match = nil, &block)
+ call_with_event("list-certs", Message.new(match), "list-cert", &block)
+ end
+
+ ##
+ # Load a connection into the daemon.
+ def load_conn(conn)
+ check_success(@transp.request("load-conn", Message.new(conn)))
+ end
+
+ ##
+ # Unload a connection from the daemon.
+ def unload_conn(conn)
+ check_success(@transp.request("unload-conn", Message.new(conn)))
+ end
+
+ ##
+ # Get the names of connections managed by vici.
+ def get_conns()
+ @transp.request("get-conns").root
+ end
+
+ ##
+ # Clear all loaded credentials.
+ def clear_creds()
+ check_success(@transp.request("clear-creds"))
+ end
+
+ ##
+ # Load a certificate into the daemon.
+ def load_cert(cert)
+ check_success(@transp.request("load-cert", Message.new(cert)))
+ end
+
+ ##
+ # Load a private key into the daemon.
+ def load_key(key)
+ check_success(@transp.request("load-key", Message.new(key)))
+ end
+
+ ##
+ # Load a shared key into the daemon.
+ def load_shared(shared)
+ check_success(@transp.request("load-shared", Message.new(shared)))
+ end
+
+ ##
+ # Load a virtual IP / attribute pool
+ def load_pool(pool)
+ check_success(@transp.request("load-pool", Message.new(pool)))
+ end
+
+ ##
+ # Unload a virtual IP / attribute pool
+ def unload_pool(pool)
+ check_success(@transp.request("unload-pool", Message.new(pool)))
+ end
+
+ ##
+ # Get the currently loaded pools.
+ def get_pools()
+ @transp.request("get-pools").root
+ end
+
+ ##
+ # Initiate a connection. The provided closure is invoked for each log line.
+ def initiate(options, &block)
+ check_success(call_with_event("initiate", Message.new(options),
+ "control-log", &block))
+ end
+
+ ##
+ # Terminate a connection. The provided closure is invoked for each log line.
+ def terminate(options, &block)
+ check_success(call_with_event("terminate", Message.new(options),
+ "control-log", &block))
+ end
+
+ ##
+ # Install a shunt/route policy.
+ def install(policy)
+ check_success(@transp.request("install", Message.new(policy)))
+ end
+
+ ##
+ # Uninstall a shunt/route policy.
+ def uninstall(policy)
+ check_success(@transp.request("uninstall", Message.new(policy)))
+ end
+
+ ##
+ # Reload strongswan.conf settings.
+ def reload_settings
+ check_success(@transp.request("reload-settings", nil))
+ end
+
+ ##
+ # Get daemon statistics and information.
+ def stats
+ @transp.request("stats", nil).root
+ end
+
+ ##
+ # Get daemon version information
+ def version
+ @transp.request("version", nil).root
+ end
+
+ ##
+ # Listen for a set of event messages. This call is blocking, and invokes
+ # the passed closure for each event received. The closure receives the
+ # event name and the event message as argument. To stop listening, the
+ # closure may raise a StopEventListening exception, the only catched
+ # exception.
+ def listen_events(events, &block)
+ self.class.instance_eval do
+ define_method(:listen_event) do |label, message|
+ block.call(label, message.root)
+ end
+ end
+ events.each do |event|
+ @transp.register(event, method(:listen_event))
+ end
+ begin
+ loop do
+ @transp.read_and_dispatch_event
+ end
+ rescue StopEventListening
+ ensure
+ events.each do |event|
+ @transp.unregister(event, method(:listen_event))
+ end
+ end
+ end
+
+ ##
+ # Issue a command request, but register for a specific event while the
+ # command is active. VICI uses this mechanism to stream potentially large
+ # data objects continuously. The provided closure is invoked for all
+ # event messages.
+ def call_with_event(command, request, event, &block)
+ self.class.instance_eval do
+ define_method(:call_event) do |label, message|
+ block.call(message.root)
+ end
+ end
+ @transp.register(event, method(:call_event))
+ begin
+ reply = @transp.request(command, request)
+ ensure
+ @transp.unregister(event, method(:call_event))
+ end
+ reply
+ end
+
+ ##
+ # Check if the reply of a command indicates "success", otherwise raise a
+ # CommandExecError exception
+ def check_success(reply)
+ root = reply.root
+ if root["success"] != "yes"
+ raise CommandExecError, root["errmsg"]
+ end
+ root
+ end
+ end
+end
diff --git a/src/libcharon/plugins/vici/ruby/vici.gemspec.in b/src/libcharon/plugins/vici/ruby/vici.gemspec.in
new file mode 100644
index 000000000..5ad61c0a0
--- /dev/null
+++ b/src/libcharon/plugins/vici/ruby/vici.gemspec.in
@@ -0,0 +1,16 @@
+Gem::Specification.new do |s|
+ s.name = "vici"
+ s.version = "@GEM_VERSION@"
+ s.authors = ["Martin Willi"]
+ s.email = ["martin@strongswan.ch"]
+ s.description = %q{
+ The strongSwan VICI protocol allows external application to monitor,
+ configure and control the IKE daemon charon. This ruby gem provides a
+ native client side implementation of the VICI protocol, well suited to
+ script automated tasks in a relaible way.
+ }
+ s.summary = "Native ruby interface for strongSwan VICI"
+ s.homepage = "https://wiki.strongswan.org/projects/strongswan/wiki/Vici"
+ s.license = "MIT"
+ s.files = "lib/vici.rb"
+end
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
index 293117348..e76d27332 100644
--- a/src/libcharon/plugins/vici/suites/test_message.c
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -347,7 +347,7 @@ START_TEST(test_get_int)
ck_assert_int_eq(m->get_int(m, 2, "section1.key2"), 0x12);
ck_assert_int_eq(m->get_int(m, 2, "section1.section2.key3"), -1);
ck_assert_int_eq(m->get_int(m, 2, "section1.key4"), 2);
- ck_assert_int_eq(m->get_int(m, 2, "key5"), 0);
+ ck_assert_int_eq(m->get_int(m, 2, "key5"), 2);
ck_assert_int_eq(m->get_int(m, 2, "nonexistent"), 2);
ck_assert_int_eq(m->get_int(m, 2, "n.o.n.e.x.i.s.t.e.n.t"), 2);
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 3cd008162..292a40032 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -450,6 +450,17 @@ CALLBACK(uninstall, vici_message_t*,
return send_reply(this, "policy '%s' not found", child);
}
+CALLBACK(reload_settings, vici_message_t*,
+ private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+ if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
+ {
+ lib->plugins->reload(lib->plugins, NULL);
+ return send_reply(this, NULL);
+ }
+ return send_reply(this, "reloading '%s' failed", lib->conf);
+}
+
static void manage_command(private_vici_control_t *this,
char *name, vici_command_cb_t cb, bool reg)
{
@@ -466,6 +477,7 @@ static void manage_commands(private_vici_control_t *this, bool reg)
manage_command(this, "terminate", terminate, reg);
manage_command(this, "install", install, reg);
manage_command(this, "uninstall", uninstall, reg);
+ manage_command(this, "reload-settings", reload_settings, reg);
this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
}
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
index cc6434b62..d4c02de6d 100644
--- a/src/libcharon/plugins/vici/vici_cred.c
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -270,13 +270,10 @@ CALLBACK(load_shared, vici_message_t*,
CALLBACK(clear_creds, vici_message_t*,
private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
{
- vici_builder_t *builder;
-
this->creds->clear(this->creds);
lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
- builder = vici_builder_create();
- return builder->finalize(builder);
+ return create_reply(NULL);
}
static void manage_command(private_vici_cred_t *this,
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
index dcc175f67..e79fbc8d3 100644
--- a/src/libcharon/plugins/vici/vici_message.c
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -355,6 +355,10 @@ METHOD(vici_message_t, vget_int, int,
found = find_value(this, &value, fmt, args);
if (found)
{
+ if (value.len == 0)
+ {
+ return def;
+ }
if (chunk_printable(value, NULL, 0))
{
snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index 8a714a9ea..b1cc1d118 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -242,6 +242,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -302,6 +303,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -367,6 +369,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -414,6 +418,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index 26bb6fb1a..e393ee163 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index f06fdb593..f0e772700 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index 72f3dc668..a4c1aaeb2 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 9af015e29..296ccaa1c 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -235,6 +235,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -295,6 +296,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -360,6 +362,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -407,6 +411,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c
index f99c0b932..fb480eee2 100644
--- a/src/libcharon/processing/jobs/adopt_children_job.c
+++ b/src/libcharon/processing/jobs/adopt_children_job.c
@@ -17,6 +17,7 @@
#include <daemon.h>
#include <hydra.h>
+#include <collections/array.h>
typedef struct private_adopt_children_job_t private_adopt_children_job_t;
@@ -34,11 +35,17 @@ struct private_adopt_children_job_t {
* IKE_SA id to adopt children from
*/
ike_sa_id_t *id;
+
+ /**
+ * Tasks queued for execution
+ */
+ array_t *tasks;
};
METHOD(job_t, destroy, void,
private_adopt_children_job_t *this)
{
+ array_destroy_offset(this->tasks, offsetof(task_t, destroy));
this->id->destroy(this->id);
free(this);
}
@@ -149,6 +156,32 @@ METHOD(job_t, execute, job_requeue_t,
}
}
children->destroy_offset(children, offsetof(child_sa_t, destroy));
+
+ if (array_count(this->tasks))
+ {
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ this->id);
+ if (ike_sa)
+ {
+ task_t *task;
+
+ while (array_remove(this->tasks, ARRAY_HEAD, &task))
+ {
+ task->migrate(task, ike_sa);
+ ike_sa->queue_task(ike_sa, task);
+ }
+ if (ike_sa->initiate(ike_sa, NULL, 0, NULL, NULL) == DESTROY_ME)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager,
+ ike_sa);
+ }
+ }
+ }
}
return JOB_REQUEUE_NONE;
}
@@ -159,6 +192,12 @@ METHOD(job_t, get_priority, job_priority_t,
return JOB_PRIO_HIGH;
}
+METHOD(adopt_children_job_t, queue_task, void,
+ private_adopt_children_job_t *this, task_t *task)
+{
+ array_insert_create(&this->tasks, ARRAY_TAIL, task);
+}
+
/**
* See header
*/
@@ -173,6 +212,7 @@ adopt_children_job_t *adopt_children_job_create(ike_sa_id_t *id)
.get_priority = _get_priority,
.destroy = _destroy,
},
+ .queue_task = _queue_task,
},
.id = id->clone(id),
);
diff --git a/src/libcharon/processing/jobs/adopt_children_job.h b/src/libcharon/processing/jobs/adopt_children_job.h
index 073504abd..ee99ee4e5 100644
--- a/src/libcharon/processing/jobs/adopt_children_job.h
+++ b/src/libcharon/processing/jobs/adopt_children_job.h
@@ -24,6 +24,7 @@
#include <library.h>
#include <processing/jobs/job.h>
#include <sa/ike_sa_id.h>
+#include <sa/task.h>
typedef struct adopt_children_job_t adopt_children_job_t;
@@ -36,6 +37,13 @@ struct adopt_children_job_t {
* Implements job_t.
*/
job_t job_interface;
+
+ /**
+ * Queue a job for execution after completing migration.
+ *
+ * @param task task to queue for execution
+ */
+ void (*queue_task)(adopt_children_job_t *this, task_t *task);
};
/**
diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c
index 694318522..e6d7da2c6 100644
--- a/src/libcharon/processing/jobs/update_sa_job.c
+++ b/src/libcharon/processing/jobs/update_sa_job.c
@@ -63,12 +63,7 @@ METHOD(job_t, execute, job_requeue_t,
}
else
{
- /* we update only if other host is NATed, but not our */
- if (ike_sa->has_condition(ike_sa, COND_NAT_THERE) &&
- !ike_sa->has_condition(ike_sa, COND_NAT_HERE))
- {
- ike_sa->update_hosts(ike_sa, NULL, this->new, FALSE);
- }
+ ike_sa->update_hosts(ike_sa, NULL, this->new, FALSE);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
return JOB_REQUEUE_NONE;
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index c338cdaef..d92b9df8e 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2013 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -16,6 +16,28 @@
* for more details.
*/
+/*
+ * Copyright (c) 2014 Volker RĂ¼melin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
@@ -251,6 +273,11 @@ struct private_ike_sa_t {
* Flush auth configs once established?
*/
bool flush_auth_cfg;
+
+ /**
+ * Maximum length of a single fragment, 0 for address-specific defaults
+ */
+ size_t fragment_size;
};
/**
@@ -909,11 +936,14 @@ METHOD(ike_sa_t, update_hosts, void,
update = TRUE;
}
- if (!other->equals(other, this->other_host))
+ if (!other->equals(other, this->other_host) &&
+ (force || has_condition(this, COND_NAT_THERE)))
{
- /* update others address if we are NOT NATed */
- if ((has_condition(this, COND_NAT_THERE) &&
- !has_condition(this, COND_NAT_HERE)) || force )
+ /* only update other's address if we are behind a static NAT,
+ * which we assume is the case if we are not initiator */
+ if (force ||
+ (!has_condition(this, COND_NAT_HERE) ||
+ !has_condition(this, COND_ORIGINAL_INITIATOR)))
{
set_other_host(this, other->clone(other));
update = TRUE;
@@ -994,6 +1024,69 @@ METHOD(ike_sa_t, generate_message, status_t,
return status;
}
+static bool filter_fragments(private_ike_sa_t *this, packet_t **fragment,
+ packet_t **packet)
+{
+ *packet = (*fragment)->clone(*fragment);
+ set_dscp(this, *packet);
+ return TRUE;
+}
+
+METHOD(ike_sa_t, generate_message_fragmented, status_t,
+ private_ike_sa_t *this, message_t *message, enumerator_t **packets)
+{
+ enumerator_t *fragments;
+ packet_t *packet;
+ status_t status;
+ bool use_frags = FALSE;
+
+ if (this->ike_cfg)
+ {
+ switch (this->ike_cfg->fragmentation(this->ike_cfg))
+ {
+ case FRAGMENTATION_FORCE:
+ use_frags = TRUE;
+ break;
+ case FRAGMENTATION_YES:
+ use_frags = supports_extension(this, EXT_IKE_FRAGMENTATION);
+ if (use_frags && this->version == IKEV1 &&
+ supports_extension(this, EXT_MS_WINDOWS))
+ {
+ /* It seems Windows 7 and 8 peers only accept proprietary
+ * fragmented messages if they expect certificates. */
+ use_frags = message->get_payload(message,
+ PLV1_CERTIFICATE) != NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (!use_frags)
+ {
+ status = generate_message(this, message, &packet);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ *packets = enumerator_create_single(packet, NULL);
+ return SUCCESS;
+ }
+
+ this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
+ message->set_ike_sa_id(message, this->ike_sa_id);
+ charon->bus->message(charon->bus, message, FALSE, TRUE);
+ status = message->fragment(message, this->keymat, this->fragment_size,
+ &fragments);
+ if (status == SUCCESS)
+ {
+ charon->bus->message(charon->bus, message, FALSE, FALSE);
+ *packets = enumerator_create_filter(fragments, (void*)filter_fragments,
+ this, NULL);
+ }
+ return status;
+}
+
METHOD(ike_sa_t, set_kmaddress, void,
private_ike_sa_t *this, host_t *local, host_t *remote)
{
@@ -1487,6 +1580,14 @@ METHOD(ike_sa_t, reauth, status_t,
{
return INVALID_STATE;
}
+ if (this->state == IKE_CONNECTING)
+ {
+ DBG0(DBG_IKE, "reinitiating IKE_SA %s[%d]",
+ get_name(this), this->unique_id);
+ reset(this);
+ this->task_manager->queue_ike(this->task_manager);
+ return this->task_manager->initiate(this->task_manager);
+ }
/* we can't reauthenticate as responder when we use EAP or virtual IPs.
* If the peer does not support RFC4478, there is no way to keep the
* IKE_SA up. */
@@ -1650,6 +1751,7 @@ METHOD(ike_sa_t, reestablish, status_t,
new->set_other_host(new, host->clone(host));
host = this->my_host;
new->set_my_host(new, host->clone(host));
+ charon->bus->ike_reestablish_pre(charon->bus, &this->public, new);
/* resolve hosts but use the old addresses above as fallback */
resolve_hosts((private_ike_sa_t*)new);
/* if we already have a virtual IP, we reuse it */
@@ -1734,12 +1836,15 @@ METHOD(ike_sa_t, reestablish, status_t,
if (status == DESTROY_ME)
{
+ charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
+ FALSE);
charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, new);
status = FAILED;
}
else
{
- charon->bus->ike_reestablish(charon->bus, &this->public, new);
+ charon->bus->ike_reestablish_post(charon->bus, &this->public, new,
+ TRUE);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, new);
status = SUCCESS;
}
@@ -1899,11 +2004,29 @@ static bool is_any_path_valid(private_ike_sa_t *this)
bool valid = FALSE;
enumerator_t *enumerator;
host_t *src = NULL, *addr;
+ int family = AF_UNSPEC;
+
+ switch (charon->socket->supported_families(charon->socket))
+ {
+ case SOCKET_FAMILY_IPV4:
+ family = AF_INET;
+ break;
+ case SOCKET_FAMILY_IPV6:
+ family = AF_INET6;
+ break;
+ case SOCKET_FAMILY_BOTH:
+ case SOCKET_FAMILY_NONE:
+ break;
+ }
DBG1(DBG_IKE, "old path is not available anymore, try to find another");
enumerator = create_peer_address_enumerator(this);
while (enumerator->enumerate(enumerator, &addr))
{
+ if (family != AF_UNSPEC && addr->get_family(addr) != family)
+ {
+ continue;
+ }
DBG1(DBG_IKE, "looking for a route to %H ...", addr);
src = hydra->kernel_interface->get_source_addr(
hydra->kernel_interface, addr, NULL);
@@ -2332,6 +2455,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.inherit_pre = _inherit_pre,
.inherit_post = _inherit_post,
.generate_message = _generate_message,
+ .generate_message_fragmented = _generate_message_fragmented,
.reset = _reset,
.get_unique_id = _get_unique_id,
.add_virtual_ip = _add_virtual_ip,
@@ -2377,6 +2501,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
"%s.retry_initiate_interval", 0, lib->ns),
.flush_auth_cfg = lib->settings->get_bool(lib->settings,
"%s.flush_auth_cfg", FALSE, lib->ns),
+ .fragment_size = lib->settings->get_int(lib->settings,
+ "%s.fragment_size", 0, lib->ns),
);
if (version == IKEV2)
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 15fb47484..c72d87367 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2012 Tobias Brunner
+ * Copyright (C) 2006-2014 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -102,7 +102,7 @@ enum ike_extension_t {
EXT_EAP_ONLY_AUTHENTICATION = (1<<5),
/**
- * peer is probably a Windows 7 RAS client
+ * peer is probably a Windows RAS client
*/
EXT_MS_WINDOWS = (1<<6),
@@ -128,7 +128,7 @@ enum ike_extension_t {
EXT_NATT_DRAFT_02_03 = (1<<10),
/**
- * peer support proprietary IKE fragmentation
+ * peer supports proprietary IKEv1 or standardized IKEv2 fragmentation
*/
EXT_IKE_FRAGMENTATION = (1<<11),
};
@@ -756,7 +756,7 @@ struct ike_sa_t {
status_t (*roam)(ike_sa_t *this, bool address);
/**
- * Processes a incoming IKEv2-Message.
+ * Processes an incoming IKE message.
*
* Message processing may fail. If a critical failure occurs,
* process_message() return DESTROY_ME. Then the caller must
@@ -768,10 +768,10 @@ struct ike_sa_t {
* - FAILED
* - DESTROY_ME if this IKE_SA MUST be deleted
*/
- status_t (*process_message) (ike_sa_t *this, message_t *message);
+ status_t (*process_message)(ike_sa_t *this, message_t *message);
/**
- * Generate a IKE message to send it to the peer.
+ * Generate an IKE message to send it to the peer.
*
* This method generates all payloads in the message and encrypts/signs
* the packet.
@@ -783,8 +783,26 @@ struct ike_sa_t {
* - FAILED
* - DESTROY_ME if this IKE_SA MUST be deleted
*/
- status_t (*generate_message) (ike_sa_t *this, message_t *message,
- packet_t **packet);
+ status_t (*generate_message)(ike_sa_t *this, message_t *message,
+ packet_t **packet);
+
+ /**
+ * Generate an IKE message to send it to the peer. If enabled and supported
+ * it will be fragmented.
+ *
+ * This method generates all payloads in the message and encrypts/signs
+ * the packet/fragments.
+ *
+ * @param message message to generate
+ * @param packets enumerator of generated packet_t* (are not destroyed
+ * with the enumerator)
+ * @return
+ * - SUCCESS
+ * - FAILED
+ * - DESTROY_ME if this IKE_SA MUST be deleted
+ */
+ status_t (*generate_message_fragmented)(ike_sa_t *this, message_t *message,
+ enumerator_t **packets);
/**
* Retransmits a request.
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 8e68e7bee..bdabc59b5 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -384,11 +384,6 @@ struct private_ike_sa_manager_t {
rng_t *rng;
/**
- * SHA1 hasher for IKE_SA_INIT retransmit detection
- */
- hasher_t *hasher;
-
- /**
* reuse existing IKE_SAs in checkout_by_config
*/
bool reuse_ikesa;
@@ -962,49 +957,39 @@ static u_int64_t get_spi(private_ike_sa_manager_t *this)
*
* @returns TRUE on success
*/
-static bool get_init_hash(private_ike_sa_manager_t *this, message_t *message,
- chunk_t *hash)
+static bool get_init_hash(hasher_t *hasher, message_t *message, chunk_t *hash)
{
host_t *src;
- if (!this->hasher)
- { /* this might be the case when flush() has been called */
- return FALSE;
- }
if (message->get_first_payload_type(message) == PLV1_FRAGMENT)
{ /* only hash the source IP, port and SPI for fragmented init messages */
u_int16_t port;
u_int64_t spi;
src = message->get_source(message);
- if (!this->hasher->allocate_hash(this->hasher,
- src->get_address(src), NULL))
+ if (!hasher->allocate_hash(hasher, src->get_address(src), NULL))
{
return FALSE;
}
port = src->get_port(src);
- if (!this->hasher->allocate_hash(this->hasher,
- chunk_from_thing(port), NULL))
+ if (!hasher->allocate_hash(hasher, chunk_from_thing(port), NULL))
{
return FALSE;
}
spi = message->get_initiator_spi(message);
- return this->hasher->allocate_hash(this->hasher,
- chunk_from_thing(spi), hash);
+ return hasher->allocate_hash(hasher, chunk_from_thing(spi), hash);
}
if (message->get_exchange_type(message) == ID_PROT)
{ /* include the source for Main Mode as the hash will be the same if
* SPIs are reused by two initiators that use the same proposal */
src = message->get_source(message);
- if (!this->hasher->allocate_hash(this->hasher,
- src->get_address(src), NULL))
+ if (!hasher->allocate_hash(hasher, src->get_address(src), NULL))
{
return FALSE;
}
}
- return this->hasher->allocate_hash(this->hasher,
- message->get_packet_data(message), hash);
+ return hasher->allocate_hash(hasher, message->get_packet_data(message), hash);
}
/**
@@ -1227,15 +1212,19 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
if (is_init)
{
+ hasher_t *hasher;
u_int64_t our_spi;
chunk_t hash;
- if (!get_init_hash(this, message, &hash))
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher || !get_init_hash(hasher, message, &hash))
{
DBG1(DBG_MGR, "ignoring message, failed to hash message");
+ DESTROY_IF(hasher);
id->destroy(id);
return NULL;
}
+ hasher->destroy(hasher);
/* ensure this is not a retransmit of an already handled init message */
switch (check_and_put_init_hash(this, hash, &our_spi))
@@ -1313,8 +1302,9 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
ike_id = entry->ike_sa->get_id(entry->ike_sa);
entry->checked_out = TRUE;
- if (message->get_first_payload_type(message) != PLV1_FRAGMENT)
- {
+ if (message->get_first_payload_type(message) != PLV1_FRAGMENT &&
+ message->get_first_payload_type(message) != PLV2_FRAGMENT)
+ { /* TODO-FRAG: this fails if there are unencrypted payloads */
entry->processing = get_message_id_or_hash(message);
}
if (ike_id->get_responder_spi(ike_id) == 0)
@@ -2058,8 +2048,6 @@ METHOD(ike_sa_manager_t, flush, void,
this->rng->destroy(this->rng);
this->rng = NULL;
- this->hasher->destroy(this->hasher);
- this->hasher = NULL;
}
METHOD(ike_sa_manager_t, destroy, void,
@@ -2134,18 +2122,10 @@ ike_sa_manager_t *ike_sa_manager_create()
},
);
- this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (this->hasher == NULL)
- {
- DBG1(DBG_MGR, "manager initialization failed, no hasher supported");
- free(this);
- return NULL;
- }
this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (this->rng == NULL)
{
DBG1(DBG_MGR, "manager initialization failed, no RNG supported");
- this->hasher->destroy(this->hasher);
free(this);
return NULL;
}
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index 114b8a3e4..d01a831f8 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -536,6 +536,7 @@ METHOD(phase1_t, select_config, peer_cfg_t*,
enumerator_t *enumerator;
peer_cfg_t *current;
host_t *me, *other;
+ int unusable = 0;
if (this->peer_cfg)
{ /* try to find an alternative config */
@@ -571,6 +572,10 @@ METHOD(phase1_t, select_config, peer_cfg_t*,
this->candidates->insert_last(this->candidates, current);
}
}
+ else
+ {
+ unusable++;
+ }
}
enumerator->destroy(enumerator);
@@ -580,6 +585,13 @@ METHOD(phase1_t, select_config, peer_cfg_t*,
this->peer_cfg->get_name(this->peer_cfg));
return this->peer_cfg->get_ref(this->peer_cfg);
}
+ if (unusable)
+ {
+ DBG1(DBG_IKE, "found %d matching config%s, but none allows %N "
+ "authentication using %s Mode", unusable, unusable > 1 ? "s" : "",
+ auth_method_names, method, aggressive ? "Aggressive" : "Main");
+ return NULL;
+ }
DBG1(DBG_IKE, "no peer config found");
return NULL;
}
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 97812a5c5..0f8e8bc6d 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2013 Tobias Brunner
+ * Copyright (C) 2007-2014 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -38,8 +38,7 @@
#include <processing/jobs/dpd_timeout_job.h>
#include <processing/jobs/process_message_job.h>
-#include <encoding/payloads/fragment_payload.h>
-#include <bio/bio_writer.h>
+#include <collections/array.h>
/**
* Number of old messages hashes we keep for retransmission.
@@ -51,20 +50,6 @@
#define MAX_OLD_HASHES 2
/**
- * Maximum packet size for fragmented packets (same as in sockets)
- */
-#define MAX_PACKET 10000
-
-/**
- * Maximum size of fragment data when sending packets (currently the same is
- * used for IPv4 and IPv6, even though the latter has a higher minimum datagram
- * size). 576 (= min. IPv4) - 20 (= IP header) - 8 (= UDP header) -
- * - 28 (= IKE header) - 8 (= fragment header) = 512
- * This is reduced by 4 in case of NAT-T (due to the non-ESP marker).
- */
-#define MAX_FRAGMENT_SIZE 512
-
-/**
* First sequence number of responding packets.
*
* To distinguish retransmission jobs for initiating and responding packets,
@@ -127,9 +112,9 @@ struct private_task_manager_t {
u_int32_t hash;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
/**
* Sequence number of the last sent message
@@ -173,9 +158,9 @@ struct private_task_manager_t {
u_int retransmitted;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
/**
* type of the initiated exchange
@@ -185,50 +170,9 @@ struct private_task_manager_t {
} initiating;
/**
- * Data used to reassemble a fragmented message
+ * Message we are currently defragmenting, if any (only one at a time)
*/
- struct {
-
- /**
- * Fragment ID (currently only one is supported at a time)
- */
- u_int16_t id;
-
- /**
- * The number of the last fragment (in case we receive the fragments out
- * of order), since the first starts with 1 this defines the number of
- * fragments we expect
- */
- u_int8_t last;
-
- /**
- * List of fragments (fragment_t*)
- */
- linked_list_t *list;
-
- /**
- * Length of all currently received fragments
- */
- size_t len;
-
- /**
- * Maximum length of a fragmented packet
- */
- size_t max_packet;
-
- /**
- * Maximum length of a single fragment (when sending)
- */
- size_t size;
-
- /**
- * The exchange type we use for fragments. Always the initial type even
- * for fragmented quick mode or transaction messages (i.e. either
- * ID_PROT or AGGRESSIVE)
- */
- exchange_type_t exchange;
-
- } frag;
+ message_t *defrag;
/**
* List of queued tasks not yet in action
@@ -277,31 +221,16 @@ struct private_task_manager_t {
};
/**
- * A single fragment within a fragmented message
+ * Reset retransmission packet list
*/
-typedef struct {
-
- /** fragment number */
- u_int8_t num;
-
- /** fragment data */
- chunk_t data;
-
-} fragment_t;
-
-static void fragment_destroy(fragment_t *this)
+static void clear_packets(array_t *array)
{
- chunk_free(&this->data);
- free(this);
-}
+ packet_t *packet;
-static void clear_fragments(private_task_manager_t *this, u_int16_t id)
-{
- DESTROY_FUNCTION_IF(this->frag.list, (void*)fragment_destroy);
- this->frag.list = NULL;
- this->frag.last = 0;
- this->frag.len = 0;
- this->frag.id = id;
+ while (array_remove(array, ARRAY_TAIL, &packet))
+ {
+ packet->destroy(packet);
+ }
}
METHOD(task_manager_t, flush_queue, void,
@@ -321,8 +250,7 @@ METHOD(task_manager_t, flush_queue, void,
list = this->active_tasks;
/* cancel pending retransmits */
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- DESTROY_IF(this->initiating.packet);
- this->initiating.packet = NULL;
+ clear_packets(this->initiating.packets);
break;
case TASK_QUEUE_PASSIVE:
list = this->passive_tasks;
@@ -373,110 +301,53 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
}
/**
- * Send a single fragment with the given data
+ * Send packets in the given array (they get cloned)
*/
-static bool send_fragment(private_task_manager_t *this, bool request,
- host_t *src, host_t *dst, fragment_payload_t *fragment)
+static void send_packets(private_task_manager_t *this, array_t *packets)
{
- message_t *message;
+ enumerator_t *enumerator;
packet_t *packet;
- status_t status;
- message = message_create(IKEV1_MAJOR_VERSION, IKEV1_MINOR_VERSION);
- /* other implementations seem to just use 0 as message ID, so here we go */
- message->set_message_id(message, 0);
- message->set_request(message, request);
- message->set_source(message, src->clone(src));
- message->set_destination(message, dst->clone(dst));
- message->set_exchange_type(message, this->frag.exchange);
- message->add_payload(message, (payload_t*)fragment);
-
- status = this->ike_sa->generate_message(this->ike_sa, message, &packet);
- if (status != SUCCESS)
+ enumerator = array_create_enumerator(packets);
+ while (enumerator->enumerate(enumerator, &packet))
{
- DBG1(DBG_IKE, "failed to generate IKE fragment");
- message->destroy(message);
- return FALSE;
+ charon->sender->send(charon->sender, packet->clone(packet));
}
- charon->sender->send(charon->sender, packet);
- message->destroy(message);
- return TRUE;
+ enumerator->destroy(enumerator);
}
/**
- * Send a packet, if supported and required do so in fragments
+ * Generates the given message and stores packet(s) in the given array
*/
-static bool send_packet(private_task_manager_t *this, bool request,
- packet_t *packet)
+static bool generate_message(private_task_manager_t *this, message_t *message,
+ array_t **packets)
{
- bool use_frags = FALSE;
- ike_cfg_t *ike_cfg;
- chunk_t data;
+ enumerator_t *fragments;
+ packet_t *fragment;
- ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
- if (ike_cfg)
+ if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
+ &fragments) != SUCCESS)
{
- switch (ike_cfg->fragmentation(ike_cfg))
- {
- case FRAGMENTATION_FORCE:
- use_frags = TRUE;
- break;
- case FRAGMENTATION_YES:
- use_frags = this->ike_sa->supports_extension(this->ike_sa,
- EXT_IKE_FRAGMENTATION);
- break;
- default:
- break;
- }
+ return FALSE;
}
- data = packet->get_data(packet);
- if (data.len > this->frag.size && use_frags)
+ while (fragments->enumerate(fragments, &fragment))
{
- fragment_payload_t *fragment;
- u_int8_t num, count;
- size_t len, frag_size;
- host_t *src, *dst;
-
- src = packet->get_source(packet);
- dst = packet->get_destination(packet);
-
- frag_size = this->frag.size;
- if (dst->get_port(dst) != IKEV2_UDP_PORT &&
- src->get_port(src) != IKEV2_UDP_PORT)
- { /* reduce size due to non-ESP marker */
- frag_size -= 4;
- }
- count = data.len / frag_size + (data.len % frag_size ? 1 : 0);
-
- DBG1(DBG_IKE, "sending IKE message with length of %zu bytes in "
- "%hhu fragments", data.len, count);
- for (num = 1; num <= count; num++)
- {
- len = min(data.len, frag_size);
- fragment = fragment_payload_create_from_data(num, num == count,
- chunk_create(data.ptr, len));
- if (!send_fragment(this, request, src, dst, fragment))
- {
- packet->destroy(packet);
- return FALSE;
- }
- data = chunk_skip(data, len);
- }
- packet->destroy(packet);
- return TRUE;
+ array_insert_create(packets, ARRAY_TAIL, fragment);
}
- charon->sender->send(charon->sender, packet);
+ fragments->destroy(fragments);
return TRUE;
}
/**
- * Retransmit a packet, either as initiator or as responder
+ * Retransmit a packet (or its fragments)
*/
-static status_t retransmit_packet(private_task_manager_t *this, bool request,
- u_int32_t seqnr, u_int mid, u_int retransmitted, packet_t *packet)
+static status_t retransmit_packet(private_task_manager_t *this, u_int32_t seqnr,
+ u_int mid, u_int retransmitted, array_t *packets)
{
+ packet_t *packet;
u_int32_t t;
+ array_get(packets, 0, &packet);
if (retransmitted > this->retransmit_tries)
{
DBG1(DBG_IKE, "giving up after %u retransmits", retransmitted - 1);
@@ -492,10 +363,7 @@ static status_t retransmit_packet(private_task_manager_t *this, bool request,
mid, seqnr < RESPONDING_SEQ ? seqnr : seqnr - RESPONDING_SEQ);
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
}
- if (!send_packet(this, request, packet->clone(packet)))
- {
- return DESTROY_ME;
- }
+ send_packets(this, packets);
lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
retransmit_job_create(seqnr, this->ike_sa->get_id(this->ike_sa)), t);
return NEED_MORE;
@@ -506,20 +374,22 @@ METHOD(task_manager_t, retransmit, status_t,
{
status_t status = SUCCESS;
- if (seqnr == this->initiating.seqnr && this->initiating.packet)
+ if (seqnr == this->initiating.seqnr &&
+ array_count(this->initiating.packets))
{
- status = retransmit_packet(this, TRUE, seqnr, this->initiating.mid,
- this->initiating.retransmitted, this->initiating.packet);
+ status = retransmit_packet(this, seqnr, this->initiating.mid,
+ this->initiating.retransmitted, this->initiating.packets);
if (status == NEED_MORE)
{
this->initiating.retransmitted++;
status = SUCCESS;
}
}
- if (seqnr == this->responding.seqnr && this->responding.packet)
+ if (seqnr == this->responding.seqnr &&
+ array_count(this->responding.packets))
{
- status = retransmit_packet(this, FALSE, seqnr, this->responding.mid,
- this->responding.retransmitted, this->responding.packet);
+ status = retransmit_packet(this, seqnr, this->responding.mid,
+ this->responding.retransmitted, this->responding.packets);
if (status == NEED_MORE)
{
this->responding.retransmitted++;
@@ -586,7 +456,6 @@ METHOD(task_manager_t, initiate, status_t,
task_t *task;
message_t *message;
host_t *me, *other;
- status_t status;
exchange_type_t exchange = EXCHANGE_TYPE_UNDEFINED;
bool new_mid = FALSE, expect_response = FALSE, cancelled = FALSE, keep = FALSE;
@@ -790,10 +659,8 @@ METHOD(task_manager_t, initiate, status_t,
return initiate(this);
}
- DESTROY_IF(this->initiating.packet);
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->initiating.packet);
- if (status != SUCCESS)
+ clear_packets(this->initiating.packets);
+ if (!generate_message(this, message, &this->initiating.packets))
{
/* message generation failed. There is nothing more to do than to
* close the SA */
@@ -811,13 +678,12 @@ METHOD(task_manager_t, initiate, status_t,
}
if (keep)
{ /* keep the packet for retransmission, the responder might request it */
- send_packet(this, TRUE,
- this->initiating.packet->clone(this->initiating.packet));
+ send_packets(this, this->initiating.packets);
}
else
{
- send_packet(this, TRUE, this->initiating.packet);
- this->initiating.packet = NULL;
+ send_packets(this, this->initiating.packets);
+ clear_packets(this->initiating.packets);
}
message->destroy(message);
@@ -848,7 +714,6 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
message_t *message;
host_t *me, *other;
bool delete = FALSE, cancelled = FALSE, expect_request = FALSE;
- status_t status;
me = request->get_destination(request);
other = request->get_source(request);
@@ -900,28 +765,25 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
}
enumerator->destroy(enumerator);
- DESTROY_IF(this->responding.packet);
- this->responding.packet = NULL;
+ clear_packets(this->responding.packets);
if (cancelled)
{
message->destroy(message);
return initiate(this);
}
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->responding.packet);
- message->destroy(message);
- if (status != SUCCESS)
+ if (!generate_message(this, message, &this->responding.packets))
{
+ message->destroy(message);
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
return DESTROY_ME;
}
+ message->destroy(message);
if (expect_request && !delete)
{
return retransmit(this, this->responding.seqnr);
}
- send_packet(this, FALSE,
- this->responding.packet->clone(this->responding.packet));
+ send_packets(this, this->responding.packets);
if (delete)
{
return DESTROY_ME;
@@ -937,7 +799,7 @@ static void send_notify(private_task_manager_t *this, message_t *request,
notify_type_t type)
{
message_t *response;
- packet_t *packet;
+ array_t *packets = NULL;
host_t *me, *other;
u_int32_t mid;
@@ -973,11 +835,12 @@ static void send_notify(private_task_manager_t *this, message_t *request,
}
response->set_source(response, me->clone(me));
response->set_destination(response, other->clone(other));
- if (this->ike_sa->generate_message(this->ike_sa, response,
- &packet) == SUCCESS)
+ if (generate_message(this, response, &packets))
{
- send_packet(this, TRUE, packet);
+ send_packets(this, packets);
}
+ clear_packets(packets);
+ array_destroy(packets);
response->destroy(response);
}
@@ -1075,7 +938,6 @@ static status_t process_request(private_task_manager_t *this,
this->passive_tasks->insert_last(this->passive_tasks, task);
task = (task_t *)isakmp_natd_create(this->ike_sa, FALSE);
this->passive_tasks->insert_last(this->passive_tasks, task);
- this->frag.exchange = AGGRESSIVE;
break;
case QUICK_MODE:
if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
@@ -1164,8 +1026,7 @@ static status_t process_request(private_task_manager_t *this,
else
{ /* We don't send a response, so don't retransmit one if we get
* the same message again. */
- DESTROY_IF(this->responding.packet);
- this->responding.packet = NULL;
+ clear_packets(this->responding.packets);
}
if (this->passive_tasks->get_count(this->passive_tasks) == 0 &&
this->queued_tasks->get_count(this->queued_tasks) > 0)
@@ -1237,8 +1098,7 @@ static status_t process_response(private_task_manager_t *this,
enumerator->destroy(enumerator);
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- DESTROY_IF(this->initiating.packet);
- this->initiating.packet = NULL;
+ clear_packets(this->initiating.packets);
if (this->queued && this->active_tasks->get_count(this->active_tasks) == 0)
{
@@ -1258,107 +1118,23 @@ static status_t process_response(private_task_manager_t *this,
static status_t handle_fragment(private_task_manager_t *this, message_t *msg)
{
- fragment_payload_t *payload;
- enumerator_t *enumerator;
- fragment_t *fragment;
- status_t status = SUCCESS;
- chunk_t data;
- u_int8_t num;
-
- payload = (fragment_payload_t*)msg->get_payload(msg, PLV1_FRAGMENT);
- if (!payload)
- {
- return FAILED;
- }
-
- if (!this->frag.list || this->frag.id != payload->get_id(payload))
- {
- clear_fragments(this, payload->get_id(payload));
- this->frag.list = linked_list_create();
- }
-
- num = payload->get_number(payload);
- if (!this->frag.last && payload->is_last(payload))
- {
- this->frag.last = num;
- }
+ status_t status;
- enumerator = this->frag.list->create_enumerator(this->frag.list);
- while (enumerator->enumerate(enumerator, &fragment))
+ if (!this->defrag)
{
- if (fragment->num == num)
- { /* ignore a duplicate fragment */
- DBG1(DBG_IKE, "received duplicate fragment #%hhu", num);
- enumerator->destroy(enumerator);
- return NEED_MORE;
- }
- if (fragment->num > num)
+ this->defrag = message_create_defrag(msg);
+ if (!this->defrag)
{
- break;
+ return FAILED;
}
}
-
- data = payload->get_data(payload);
- this->frag.len += data.len;
- if (this->frag.len > this->frag.max_packet)
- {
- DBG1(DBG_IKE, "fragmented IKE message is too large");
- enumerator->destroy(enumerator);
- clear_fragments(this, 0);
- return FAILED;
- }
-
- INIT(fragment,
- .num = num,
- .data = chunk_clone(data),
- );
-
- this->frag.list->insert_before(this->frag.list, enumerator, fragment);
- enumerator->destroy(enumerator);
-
- if (this->frag.list->get_count(this->frag.list) == this->frag.last)
+ status = this->defrag->add_fragment(this->defrag, msg);
+ if (status == SUCCESS)
{
- message_t *message;
- packet_t *pkt;
- host_t *src, *dst;
- bio_writer_t *writer;
-
- writer = bio_writer_create(this->frag.len);
- DBG1(DBG_IKE, "received fragment #%hhu, reassembling fragmented IKE "
- "message", num);
- enumerator = this->frag.list->create_enumerator(this->frag.list);
- while (enumerator->enumerate(enumerator, &fragment))
- {
- writer->write_data(writer, fragment->data);
- }
- enumerator->destroy(enumerator);
-
- src = msg->get_source(msg);
- dst = msg->get_destination(msg);
- pkt = packet_create_from_data(src->clone(src), dst->clone(dst),
- writer->extract_buf(writer));
- writer->destroy(writer);
-
- message = message_create_from_packet(pkt);
- if (message->parse_header(message) != SUCCESS)
- {
- DBG1(DBG_IKE, "failed to parse header of reassembled IKE message");
- message->destroy(message);
- status = FAILED;
- }
- else
- {
- lib->processor->queue_job(lib->processor,
- (job_t*)process_message_job_create(message));
- status = NEED_MORE;
-
- }
- clear_fragments(this, 0);
- }
- else
- { /* there are some fragments missing */
- DBG1(DBG_IKE, "received fragment #%hhu, waiting for complete IKE "
- "message", num);
+ lib->processor->queue_job(lib->processor,
+ (job_t*)process_message_job_create(this->defrag));
+ this->defrag = NULL;
+ /* do not process the last fragment */
status = NEED_MORE;
}
return status;
@@ -1435,15 +1211,14 @@ METHOD(task_manager_t, process_message, status_t,
{
if (this->initiating.old_hashes[i] == hash)
{
- if (this->initiating.packet &&
+ if (array_count(this->initiating.packets) &&
i == (this->initiating.old_hash_pos % MAX_OLD_HASHES) &&
(msg->get_exchange_type(msg) == QUICK_MODE ||
msg->get_exchange_type(msg) == AGGRESSIVE))
{
DBG1(DBG_IKE, "received retransmit of response with ID %u, "
"resending last request", mid);
- send_packet(this, TRUE,
- this->initiating.packet->clone(this->initiating.packet));
+ send_packets(this, this->initiating.packets);
return SUCCESS;
}
DBG1(DBG_IKE, "received retransmit of response with ID %u, "
@@ -1484,20 +1259,18 @@ METHOD(task_manager_t, process_message, status_t,
{
if (hash == this->responding.hash)
{
- if (this->responding.packet)
+ if (array_count(this->responding.packets))
{
DBG1(DBG_IKE, "received retransmit of request with ID %u, "
"retransmitting response", mid);
- send_packet(this, FALSE,
- this->responding.packet->clone(this->responding.packet));
+ send_packets(this, this->responding.packets);
}
- else if (this->initiating.packet &&
+ else if (array_count(this->initiating.packets) &&
this->initiating.type == INFORMATIONAL_V1)
{
DBG1(DBG_IKE, "received retransmit of DPD request, "
"retransmitting response");
- send_packet(this, TRUE,
- this->initiating.packet->clone(this->initiating.packet));
+ send_packets(this, this->initiating.packets);
}
else
{
@@ -1593,13 +1366,6 @@ METHOD(task_manager_t, process_message, status_t,
return SUCCESS;
}
-METHOD(task_manager_t, queue_task, void,
- private_task_manager_t *this, task_t *task)
-{
- DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
- this->queued_tasks->insert_last(this->queued_tasks, task);
-}
-
/**
* Check if a given task has been queued already
*/
@@ -1622,6 +1388,28 @@ static bool has_queued(private_task_manager_t *this, task_type_t type)
return found;
}
+METHOD(task_manager_t, queue_task, void,
+ private_task_manager_t *this, task_t *task)
+{
+ task_type_t type = task->get_type(task);
+
+ switch (type)
+ {
+ case TASK_MODE_CONFIG:
+ case TASK_XAUTH:
+ if (has_queued(this, type))
+ {
+ task->destroy(task);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
+ this->queued_tasks->insert_last(this->queued_tasks, task);
+}
+
METHOD(task_manager_t, queue_ike, void,
private_task_manager_t *this)
{
@@ -1642,7 +1430,6 @@ METHOD(task_manager_t, queue_ike, void,
{
queue_task(this, (task_t*)aggressive_mode_create(this->ike_sa, TRUE));
}
- this->frag.exchange = AGGRESSIVE;
}
else
{
@@ -1969,17 +1756,16 @@ METHOD(task_manager_t, reset, void,
task_t *task;
/* reset message counters and retransmit packets */
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
- this->responding.packet = NULL;
+ clear_packets(this->responding.packets);
+ clear_packets(this->initiating.packets);
this->responding.seqnr = RESPONDING_SEQ;
this->responding.retransmitted = 0;
- this->initiating.packet = NULL;
this->initiating.mid = 0;
this->initiating.seqnr = 0;
this->initiating.retransmitted = 0;
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- clear_fragments(this, 0);
+ DESTROY_IF(this->defrag);
+ this->defrag = NULL;
if (initiate != UINT_MAX)
{
this->dpd_send = initiate;
@@ -2030,11 +1816,13 @@ METHOD(task_manager_t, destroy, void,
this->active_tasks->destroy(this->active_tasks);
this->queued_tasks->destroy(this->queued_tasks);
this->passive_tasks->destroy(this->passive_tasks);
- clear_fragments(this, 0);
+ DESTROY_IF(this->defrag);
DESTROY_IF(this->queued);
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
+ clear_packets(this->responding.packets);
+ array_destroy(this->responding.packets);
+ clear_packets(this->initiating.packets);
+ array_destroy(this->initiating.packets);
DESTROY_IF(this->rng);
free(this);
}
@@ -2079,13 +1867,6 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
.responding = {
.seqnr = RESPONDING_SEQ,
},
- .frag = {
- .exchange = ID_PROT,
- .max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, lib->ns),
- .size = lib->settings->get_int(lib->settings,
- "%s.fragment_size", MAX_FRAGMENT_SIZE, lib->ns),
- },
.ike_sa = ike_sa,
.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
.queued_tasks = linked_list_create(),
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 7009ae95d..710bf1cd2 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -475,6 +475,9 @@ METHOD(task_t, process_r, status_t,
}
case AM_AUTH:
{
+ adopt_children_job_t *job = NULL;
+ xauth_t *xauth = NULL;
+
while (TRUE)
{
if (this->ph1->verify_auth(this->ph1, this->method, message,
@@ -504,8 +507,8 @@ METHOD(task_t, process_r, status_t,
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
case AUTH_HYBRID_INIT_RSA:
- this->ike_sa->queue_task(this->ike_sa,
- (task_t*)xauth_create(this->ike_sa, TRUE));
+ xauth = xauth_create(this->ike_sa, TRUE);
+ this->ike_sa->queue_task(this->ike_sa, (task_t*)xauth);
break;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
@@ -524,9 +527,8 @@ METHOD(task_t, process_r, status_t,
{
return send_delete(this);
}
- lib->processor->queue_job(lib->processor, (job_t*)
- adopt_children_job_create(
- this->ike_sa->get_id(this->ike_sa)));
+ job = adopt_children_job_create(
+ this->ike_sa->get_id(this->ike_sa));
break;
}
/* check for and prepare mode config push/pull */
@@ -542,10 +544,26 @@ METHOD(task_t, process_r, status_t,
{
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
{
- this->ike_sa->queue_task(this->ike_sa,
- (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
+ if (job)
+ {
+ job->queue_task(job, (task_t*)
+ mode_config_create(this->ike_sa, TRUE, FALSE));
+ }
+ else if (xauth)
+ {
+ xauth->queue_mode_config_push(xauth);
+ }
+ else
+ {
+ this->ike_sa->queue_task(this->ike_sa, (task_t*)
+ mode_config_create(this->ike_sa, TRUE, FALSE));
+ }
}
}
+ if (job)
+ {
+ lib->processor->queue_job(lib->processor, (job_t*)job);
+ }
return SUCCESS;
}
default:
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
index b742dbef9..2798978b2 100644
--- a/src/libcharon/sa/ikev1/tasks/informational.c
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -112,16 +112,16 @@ METHOD(task_t, process_r, status_t,
IKEV2_UDP_PORT);
if (redirect)
{ /* treat the redirect as reauthentication */
- DBG1(DBG_IKE, "received %N notify. redirected to %H",
+ DBG1(DBG_IKE, "received %N notify, redirected to %H",
notify_type_names, type, redirect);
/* Cisco boxes reject the first message from 4500 */
me = this->ike_sa->get_my_host(this->ike_sa);
me->set_port(me, charon->socket->get_port(
charon->socket, FALSE));
this->ike_sa->set_other_host(this->ike_sa, redirect);
- this->ike_sa->reauth(this->ike_sa);
+ status = this->ike_sa->reauth(this->ike_sa);
enumerator->destroy(enumerator);
- return DESTROY_ME;
+ return status;
}
else
{
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
index 426c4bd69..0162fd84e 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -15,7 +15,7 @@
*/
/*
- * Copyright (C) 2012 Volker RĂ¼melin
+ * Copyright (C) 2012-2014 Volker RĂ¼melin
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -106,10 +106,15 @@ static struct {
"\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
/* Proprietary IKE fragmentation extension. Capabilities are handled
- * specially on receipt of this VID. */
+ * specially on receipt of this VID. Windows peers send this VID
+ * without capabilities, but accept it with and without capabilities. */
{ "FRAGMENTATION", EXT_IKE_FRAGMENTATION, FALSE, 20,
"\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x80\x00\x00\x00"},
+ /* Windows peers send this VID and a version number */
+ { "MS NT5 ISAKMPOAKLEY", EXT_MS_WINDOWS, FALSE, 20,
+ "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x00"},
+
}, vendor_natt_ids[] = {
/* NAT-Traversal VIDs ordered by preference */
@@ -167,15 +172,27 @@ static struct {
*/
static const u_int32_t fragmentation_ike = 0x80000000;
-/**
- * Check if the given vendor ID indicate support for fragmentation
- */
-static bool fragmentation_supported(chunk_t data, int i)
+static bool is_known_vid(chunk_t data, int i)
{
- if (vendor_ids[i].extension == EXT_IKE_FRAGMENTATION &&
- data.len == 20 && memeq(data.ptr, vendor_ids[i].id, 16))
+ switch (vendor_ids[i].extension)
{
- return untoh32(&data.ptr[16]) & fragmentation_ike;
+ case EXT_IKE_FRAGMENTATION:
+ if (data.len >= 16 && memeq(data.ptr, vendor_ids[i].id, 16))
+ {
+ switch (data.len)
+ {
+ case 16:
+ return TRUE;
+ case 20:
+ return untoh32(&data.ptr[16]) & fragmentation_ike;
+ }
+ }
+ break;
+ case EXT_MS_WINDOWS:
+ return data.len == 20 && memeq(data.ptr, vendor_ids[i].id, 16);
+ default:
+ return chunk_equals(data, chunk_create(vendor_ids[i].id,
+ vendor_ids[i].len));
}
return FALSE;
}
@@ -251,9 +268,7 @@ static void process(private_isakmp_vendor_t *this, message_t *message)
for (i = 0; i < countof(vendor_ids); i++)
{
- if (chunk_equals(data, chunk_create(vendor_ids[i].id,
- vendor_ids[i].len)) ||
- fragmentation_supported(data, i))
+ if (is_known_vid(data, i))
{
DBG1(DBG_IKE, "received %s vendor ID", vendor_ids[i].desc);
if (vendor_ids[i].extension)
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 8a5d9ae16..2fb4c6935 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -479,6 +479,8 @@ METHOD(task_t, build_r, status_t,
{
id_payload_t *id_payload;
identification_t *id;
+ adopt_children_job_t *job = NULL;
+ xauth_t *xauth = NULL;
id = this->ph1->get_id(this->ph1, this->peer_cfg, TRUE);
if (!id)
@@ -502,8 +504,8 @@ METHOD(task_t, build_r, status_t,
case AUTH_XAUTH_INIT_PSK:
case AUTH_XAUTH_INIT_RSA:
case AUTH_HYBRID_INIT_RSA:
- this->ike_sa->queue_task(this->ike_sa,
- (task_t*)xauth_create(this->ike_sa, TRUE));
+ xauth = xauth_create(this->ike_sa, TRUE);
+ this->ike_sa->queue_task(this->ike_sa, (task_t*)xauth);
break;
case AUTH_XAUTH_RESP_PSK:
case AUTH_XAUTH_RESP_RSA:
@@ -522,9 +524,8 @@ METHOD(task_t, build_r, status_t,
{
return send_notify(this, AUTHENTICATION_FAILED);
}
- lib->processor->queue_job(lib->processor, (job_t*)
- adopt_children_job_create(
- this->ike_sa->get_id(this->ike_sa)));
+ job = adopt_children_job_create(
+ this->ike_sa->get_id(this->ike_sa));
break;
}
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
@@ -539,10 +540,26 @@ METHOD(task_t, build_r, status_t,
{
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
{
- this->ike_sa->queue_task(this->ike_sa,
- (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
+ if (job)
+ {
+ job->queue_task(job, (task_t*)
+ mode_config_create(this->ike_sa, TRUE, FALSE));
+ }
+ else if (xauth)
+ {
+ xauth->queue_mode_config_push(xauth);
+ }
+ else
+ {
+ this->ike_sa->queue_task(this->ike_sa, (task_t*)
+ mode_config_create(this->ike_sa, TRUE, FALSE));
+ }
}
}
+ if (job)
+ {
+ lib->processor->queue_job(lib->processor, (job_t*)job);
+ }
return SUCCESS;
}
default:
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index e6273682d..1133aab65 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -1030,7 +1030,8 @@ METHOD(task_t, process_r, status_t,
}
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
- if (!this->config || !this->tsi || !this->tsr)
+ if (!this->config || !this->tsi || !this->tsr ||
+ this->mode != this->config->get_mode(this->config))
{
DBG1(DBG_IKE, "no matching CHILD_SA config found");
return send_notify(this, INVALID_ID_INFORMATION);
@@ -1117,11 +1118,22 @@ METHOD(task_t, process_r, status_t,
}
case QM_NEGOTIATED:
{
- if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
- has_notify_errors(this, message))
+ if (has_notify_errors(this, message))
{
return SUCCESS;
}
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1)
+ {
+ if (message->get_payload(message, PLV1_DELETE))
+ {
+ /* If the DELETE for a Quick Mode follows immediately
+ * after rekeying, we might receive it before the
+ * third completing Quick Mode message. Ignore it, as
+ * it gets handled by a separately queued delete task. */
+ return NEED_MORE;
+ }
+ return SUCCESS;
+ }
if (!install(this))
{
ike_sa_t *ike_sa = this->ike_sa;
@@ -1198,6 +1210,14 @@ METHOD(task_t, build_r, status_t,
this->state = QM_NEGOTIATED;
return NEED_MORE;
}
+ case QM_NEGOTIATED:
+ if (message->get_exchange_type(message) == INFORMATIONAL_V1)
+ {
+ /* skip INFORMATIONAL response if we received a INFORMATIONAL
+ * delete, see process_r() */
+ return ALREADY_DONE;
+ }
+ /* fall */
default:
return FAILED;
}
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c
index bdc5d67f7..a770e90ff 100644
--- a/src/libcharon/sa/ikev1/tasks/xauth.c
+++ b/src/libcharon/sa/ikev1/tasks/xauth.c
@@ -19,6 +19,7 @@
#include <hydra.h>
#include <encoding/payloads/cp_payload.h>
#include <processing/jobs/adopt_children_job.h>
+#include <sa/ikev1/tasks/mode_config.h>
typedef struct private_xauth_t private_xauth_t;
@@ -74,6 +75,11 @@ struct private_xauth_t {
* status of Xauth exchange
*/
xauth_status_t status;
+
+ /**
+ * Queue a Mode Config Push mode after completing XAuth?
+ */
+ bool mode_config_push;
};
/**
@@ -290,6 +296,7 @@ METHOD(task_t, process_i_status, status_t,
private_xauth_t *this, message_t *message)
{
cp_payload_t *cp;
+ adopt_children_job_t *job;
cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
if (!cp || cp->get_type(cp) != CFG_ACK)
@@ -307,8 +314,13 @@ METHOD(task_t, process_i_status, status_t,
return FAILED;
}
this->ike_sa->set_condition(this->ike_sa, COND_XAUTH_AUTHENTICATED, TRUE);
- lib->processor->queue_job(lib->processor, (job_t*)
- adopt_children_job_create(this->ike_sa->get_id(this->ike_sa)));
+ job = adopt_children_job_create(this->ike_sa->get_id(this->ike_sa));
+ if (this->mode_config_push)
+ {
+ job->queue_task(job,
+ (task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
+ }
+ lib->processor->queue_job(lib->processor, (job_t*)job);
return SUCCESS;
}
@@ -511,6 +523,12 @@ METHOD(task_t, migrate, void,
}
}
+METHOD(xauth_t, queue_mode_config_push, void,
+ private_xauth_t *this)
+{
+ this->mode_config_push = TRUE;
+}
+
METHOD(task_t, destroy, void,
private_xauth_t *this)
{
@@ -533,6 +551,7 @@ xauth_t *xauth_create(ike_sa_t *ike_sa, bool initiator)
.migrate = _migrate,
.destroy = _destroy,
},
+ .queue_mode_config_push = _queue_mode_config_push,
},
.initiator = initiator,
.ike_sa = ike_sa,
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.h b/src/libcharon/sa/ikev1/tasks/xauth.h
index 303eb31ce..ffaf32a32 100644
--- a/src/libcharon/sa/ikev1/tasks/xauth.h
+++ b/src/libcharon/sa/ikev1/tasks/xauth.h
@@ -36,6 +36,11 @@ struct xauth_t {
* Implements the task_t interface
*/
task_t task;
+
+ /**
+ * Queue a Mode Config in Push mode after completing XAuth.
+ */
+ void (*queue_mode_config_push)(xauth_t *this);
};
/**
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index ada798bdc..eb7df3516 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2011 Tobias Brunner
+ * Copyright (C) 2007-2014 Tobias Brunner
* Copyright (C) 2007-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -90,9 +90,14 @@ struct private_task_manager_t {
u_int32_t mid;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
+
+ /**
+ * Helper to defragment the request
+ */
+ message_t *defrag;
} responding;
@@ -111,15 +116,25 @@ struct private_task_manager_t {
u_int retransmitted;
/**
- * packet for retransmission
+ * packet(s) for retransmission
*/
- packet_t *packet;
+ array_t *packets;
/**
* type of the initated exchange
*/
exchange_type_t type;
+ /**
+ * TRUE if exchange was deferred because no path was available
+ */
+ bool deferred;
+
+ /**
+ * Helper to defragment the response
+ */
+ message_t *defrag;
+
} initiating;
/**
@@ -158,6 +173,19 @@ struct private_task_manager_t {
double retransmit_base;
};
+/**
+ * Reset retransmission packet list
+ */
+static void clear_packets(array_t *array)
+{
+ packet_t *packet;
+
+ while (array_remove(array, ARRAY_TAIL, &packet))
+ {
+ packet->destroy(packet);
+ }
+}
+
METHOD(task_manager_t, flush_queue, void,
private_task_manager_t *this, task_queue_t queue)
{
@@ -217,10 +245,60 @@ static bool activate_task(private_task_manager_t *this, task_type_t type)
return found;
}
+/**
+ * Send packets in the given array (they get cloned). Optionally, the
+ * source and destination addresses are changed before sending it.
+ */
+static void send_packets(private_task_manager_t *this, array_t *packets,
+ host_t *src, host_t *dst)
+{
+ packet_t *packet, *clone;
+ int i;
+
+ for (i = 0; i < array_count(packets); i++)
+ {
+ array_get(packets, i, &packet);
+ clone = packet->clone(packet);
+ if (src)
+ {
+ clone->set_source(clone, src->clone(src));
+ }
+ if (dst)
+ {
+ clone->set_destination(clone, dst->clone(dst));
+ }
+ charon->sender->send(charon->sender, clone);
+ }
+}
+
+/**
+ * Generates the given message and stores packet(s) in the given array
+ */
+static bool generate_message(private_task_manager_t *this, message_t *message,
+ array_t **packets)
+{
+ enumerator_t *fragments;
+ packet_t *fragment;
+
+ if (this->ike_sa->generate_message_fragmented(this->ike_sa, message,
+ &fragments) != SUCCESS)
+ {
+ return FALSE;
+ }
+ while (fragments->enumerate(fragments, &fragment))
+ {
+ array_insert_create(packets, ARRAY_TAIL, fragment);
+ }
+ fragments->destroy(fragments);
+ array_compress(*packets);
+ return TRUE;
+}
+
METHOD(task_manager_t, retransmit, status_t,
private_task_manager_t *this, u_int32_t message_id)
{
- if (this->initiating.packet && message_id == this->initiating.mid)
+ if (message_id == this->initiating.mid &&
+ array_count(this->initiating.packets))
{
u_int32_t timeout;
job_t *job;
@@ -229,23 +307,24 @@ METHOD(task_manager_t, retransmit, status_t,
task_t *task;
ike_mobike_t *mobike = NULL;
+ array_get(this->initiating.packets, 0, &packet);
+
/* check if we are retransmitting a MOBIKE routability check */
- enumerator = array_create_enumerator(this->active_tasks);
- while (enumerator->enumerate(enumerator, (void*)&task))
+ if (this->initiating.type == INFORMATIONAL)
{
- if (task->get_type(task) == TASK_IKE_MOBIKE)
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, (void*)&task))
{
- mobike = (ike_mobike_t*)task;
- if (!mobike->is_probing(mobike))
+ if (task->get_type(task) == TASK_IKE_MOBIKE)
{
- mobike = NULL;
+ mobike = (ike_mobike_t*)task;
+ break;
}
- break;
}
+ enumerator->destroy(enumerator);
}
- enumerator->destroy(enumerator);
- if (mobike == NULL)
+ if (!mobike || !mobike->is_probing(mobike))
{
if (this->initiating.retransmitted <= this->retransmit_tries)
{
@@ -257,7 +336,7 @@ METHOD(task_manager_t, retransmit, status_t,
DBG1(DBG_IKE, "giving up after %d retransmits",
this->initiating.retransmitted - 1);
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT,
- this->initiating.packet);
+ packet);
return DESTROY_ME;
}
@@ -265,11 +344,29 @@ METHOD(task_manager_t, retransmit, status_t,
{
DBG1(DBG_IKE, "retransmit %d of request with message ID %d",
this->initiating.retransmitted, message_id);
- charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND,
- this->initiating.packet);
+ charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, packet);
+ }
+ if (!mobike)
+ {
+ send_packets(this, this->initiating.packets,
+ this->ike_sa->get_my_host(this->ike_sa),
+ this->ike_sa->get_other_host(this->ike_sa));
+ }
+ else
+ {
+ if (!mobike->transmit(mobike, packet))
+ {
+ DBG1(DBG_IKE, "no route found to reach peer, MOBIKE update "
+ "deferred");
+ this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
+ this->initiating.deferred = TRUE;
+ return SUCCESS;
+ }
+ else if (mobike->is_probing(mobike))
+ {
+ timeout = ROUTEABILITY_CHECK_INTERVAL;
+ }
}
- packet = this->initiating.packet->clone(this->initiating.packet);
- charon->sender->send(charon->sender, packet);
}
else
{ /* for routeability checks, we use a more aggressive behavior */
@@ -289,7 +386,16 @@ METHOD(task_manager_t, retransmit, status_t,
DBG1(DBG_IKE, "path probing attempt %d",
this->initiating.retransmitted);
}
- mobike->transmit(mobike, this->initiating.packet);
+ /* TODO-FRAG: presumably these small packets are not fragmented,
+ * we should maybe ensure this is the case when generating them */
+ if (!mobike->transmit(mobike, packet))
+ {
+ DBG1(DBG_IKE, "no route found to reach peer, path probing "
+ "deferred");
+ this->ike_sa->set_condition(this->ike_sa, COND_STALE, TRUE);
+ this->initiating.deferred = TRUE;
+ return SUCCESS;
+ }
}
this->initiating.retransmitted++;
@@ -307,7 +413,6 @@ METHOD(task_manager_t, initiate, status_t,
task_t *task;
message_t *message;
host_t *me, *other;
- status_t status;
exchange_type_t exchange = 0;
if (this->initiating.type != EXCHANGE_TYPE_UNDEFINED)
@@ -315,6 +420,12 @@ METHOD(task_manager_t, initiate, status_t,
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 */
+ if (this->initiating.deferred)
+ { /* re-initiate deferred exchange */
+ this->initiating.deferred = FALSE;
+ this->initiating.retransmitted = 0;
+ return retransmit(this, this->initiating.mid);
+ }
return SUCCESS;
}
@@ -347,39 +458,39 @@ METHOD(task_manager_t, initiate, status_t,
}
break;
case IKE_ESTABLISHED:
- if (activate_task(this, TASK_CHILD_CREATE))
+ if (activate_task(this, TASK_IKE_MOBIKE))
{
- exchange = CREATE_CHILD_SA;
+ exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_CHILD_DELETE))
+ if (activate_task(this, TASK_IKE_DELETE))
{
exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_CHILD_REKEY))
+ if (activate_task(this, TASK_CHILD_DELETE))
{
- exchange = CREATE_CHILD_SA;
+ exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_IKE_DELETE))
+ if (activate_task(this, TASK_IKE_REAUTH))
{
exchange = INFORMATIONAL;
break;
}
- if (activate_task(this, TASK_IKE_REKEY))
+ if (activate_task(this, TASK_CHILD_CREATE))
{
exchange = CREATE_CHILD_SA;
break;
}
- if (activate_task(this, TASK_IKE_REAUTH))
+ if (activate_task(this, TASK_CHILD_REKEY))
{
- exchange = INFORMATIONAL;
+ exchange = CREATE_CHILD_SA;
break;
}
- if (activate_task(this, TASK_IKE_MOBIKE))
+ if (activate_task(this, TASK_IKE_REKEY))
{
- exchange = INFORMATIONAL;
+ exchange = CREATE_CHILD_SA;
break;
}
if (activate_task(this, TASK_IKE_DPD))
@@ -458,6 +569,7 @@ METHOD(task_manager_t, initiate, status_t,
message->set_exchange_type(message, exchange);
this->initiating.type = exchange;
this->initiating.retransmitted = 0;
+ this->initiating.deferred = FALSE;
enumerator = array_create_enumerator(this->active_tasks);
while (enumerator->enumerate(enumerator, &task))
@@ -493,9 +605,7 @@ METHOD(task_manager_t, initiate, status_t,
/* update exchange type if a task changed it */
this->initiating.type = message->get_exchange_type(message);
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->initiating.packet);
- if (status != SUCCESS)
+ if (!generate_message(this, message, &this->initiating.packets))
{
/* message generation failed. There is nothing more to do than to
* close the SA */
@@ -567,8 +677,7 @@ static status_t process_response(private_task_manager_t *this,
this->initiating.mid++;
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
- this->initiating.packet->destroy(this->initiating.packet);
- this->initiating.packet = NULL;
+ clear_packets(this->initiating.packets);
array_compress(this->active_tasks);
@@ -636,8 +745,8 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
host_t *me, *other;
bool delete = FALSE, hook = FALSE;
ike_sa_id_t *id = NULL;
- u_int64_t responder_spi;
- status_t status;
+ u_int64_t responder_spi = 0;
+ bool result;
me = request->get_destination(request);
other = request->get_source(request);
@@ -699,23 +808,20 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
}
/* message complete, send it */
- DESTROY_IF(this->responding.packet);
- this->responding.packet = NULL;
- status = this->ike_sa->generate_message(this->ike_sa, message,
- &this->responding.packet);
+ clear_packets(this->responding.packets);
+ result = generate_message(this, message, &this->responding.packets);
message->destroy(message);
if (id)
{
id->set_responder_spi(id, responder_spi);
}
- if (status != SUCCESS)
+ if (!result)
{
charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
return DESTROY_ME;
}
- charon->sender->send(charon->sender,
- this->responding.packet->clone(this->responding.packet));
+ send_packets(this, this->responding.packets, NULL, NULL);
if (delete)
{
if (hook)
@@ -964,6 +1070,48 @@ METHOD(task_manager_t, incr_mid, void,
}
/**
+ * Handle the given IKE fragment, if it is one.
+ *
+ * Returns SUCCESS if the message is not a fragment, and NEED_MORE if it was
+ * handled properly. Error states are returned if the fragment was invalid or
+ * the reassembled message could not have been processed properly.
+ */
+static status_t handle_fragment(private_task_manager_t *this,
+ message_t **defrag, message_t *msg)
+{
+ message_t *reassembled;
+ status_t status;
+
+ if (!msg->get_payload(msg, PLV2_FRAGMENT))
+ {
+ return SUCCESS;
+ }
+ if (!*defrag)
+ {
+ *defrag = message_create_defrag(msg);
+ if (!*defrag)
+ {
+ return FAILED;
+ }
+ }
+ status = (*defrag)->add_fragment(*defrag, msg);
+ if (status == SUCCESS)
+ {
+ /* reinject the reassembled message */
+ reassembled = *defrag;
+ *defrag = NULL;
+ status = this->ike_sa->process_message(this->ike_sa, reassembled);
+ if (status == SUCCESS)
+ {
+ /* avoid processing the last fragment */
+ status = NEED_MORE;
+ }
+ reassembled->destroy(reassembled);
+ }
+ return status;
+}
+
+/**
* Send a notify back to the sender
*/
static void send_notify_response(private_task_manager_t *this,
@@ -1156,6 +1304,11 @@ METHOD(task_manager_t, process_message, status_t,
{ /* with MOBIKE, we do no implicit updates */
this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
}
+ status = handle_fragment(this, &this->responding.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
@@ -1168,20 +1321,19 @@ METHOD(task_manager_t, process_message, status_t,
}
this->responding.mid++;
}
- else if ((mid == this->responding.mid - 1) && this->responding.packet)
+ else if ((mid == this->responding.mid - 1) &&
+ array_count(this->responding.packets))
{
- packet_t *clone;
- host_t *host;
-
+ status = handle_fragment(this, &this->responding.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
DBG1(DBG_IKE, "received retransmit of request with ID %d, "
"retransmitting response", mid);
charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg);
- clone = this->responding.packet->clone(this->responding.packet);
- host = msg->get_destination(msg);
- clone->set_source(clone, host->clone(host));
- host = msg->get_source(msg);
- clone->set_destination(clone, host->clone(host));
- charon->sender->send(charon->sender, clone);
+ send_packets(this, this->responding.packets,
+ msg->get_destination(msg), msg->get_source(msg));
}
else
{
@@ -1209,6 +1361,11 @@ METHOD(task_manager_t, process_message, status_t,
this->ike_sa->update_hosts(this->ike_sa, NULL, other, FALSE);
}
}
+ status = handle_fragment(this, &this->initiating.defrag, msg);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (msg->get_exchange_type(msg) == EXCHANGE_TYPE_UNDEFINED)
{ /* ignore messages altered to EXCHANGE_TYPE_UNDEFINED */
@@ -1368,7 +1525,25 @@ METHOD(task_manager_t, queue_mobike, void,
mobike = ike_mobike_create(this->ike_sa, TRUE);
if (roam)
{
+ enumerator_t *enumerator;
+ task_t *current;
+
mobike->roam(mobike, address);
+
+ /* enable path probing for a currently active MOBIKE task. This might
+ * not be the case if an address appeared on a new interface while the
+ * current address is not working but has not yet disappeared. */
+ enumerator = array_create_enumerator(this->active_tasks);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->get_type(current) == TASK_IKE_MOBIKE)
+ {
+ ike_mobike_t *active = (ike_mobike_t*)current;
+ active->enable_probing(active);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
}
else
{
@@ -1485,10 +1660,12 @@ METHOD(task_manager_t, reset, void,
task_t *task;
/* reset message counters and retransmit packets */
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
- this->responding.packet = NULL;
- this->initiating.packet = NULL;
+ clear_packets(this->responding.packets);
+ clear_packets(this->initiating.packets);
+ DESTROY_IF(this->responding.defrag);
+ DESTROY_IF(this->initiating.defrag);
+ this->responding.defrag = NULL;
+ this->initiating.defrag = NULL;
if (initiate != UINT_MAX)
{
this->initiating.mid = initiate;
@@ -1542,8 +1719,12 @@ METHOD(task_manager_t, destroy, void,
array_destroy(this->queued_tasks);
array_destroy(this->passive_tasks);
- DESTROY_IF(this->responding.packet);
- DESTROY_IF(this->initiating.packet);
+ clear_packets(this->responding.packets);
+ array_destroy(this->responding.packets);
+ clear_packets(this->initiating.packets);
+ array_destroy(this->initiating.packets);
+ DESTROY_IF(this->responding.defrag);
+ DESTROY_IF(this->initiating.defrag);
free(this);
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index e3c18ea0f..71c5f22fa 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -161,6 +161,19 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
message->add_payload(message, (payload_t*)ke_payload);
message->add_payload(message, (payload_t*)nonce_payload);
}
+
+ /* negotiate fragmentation if we are not rekeying */
+ if (!this->old_sa &&
+ this->config->fragmentation(this->config) != FRAGMENTATION_NO)
+ {
+ if (this->initiator ||
+ this->ike_sa->supports_extension(this->ike_sa,
+ EXT_IKE_FRAGMENTATION))
+ {
+ message->add_notify(message, FALSE, FRAGMENTATION_SUPPORTED,
+ chunk_empty);
+ }
+ }
}
/**
@@ -220,6 +233,16 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
this->other_nonce = nonce_payload->get_nonce(nonce_payload);
break;
}
+ case PLV2_NOTIFY:
+ {
+ notify_payload_t *notify = (notify_payload_t*)payload;
+
+ if (notify->get_notify_type(notify) == FRAGMENTATION_SUPPORTED)
+ {
+ this->ike_sa->enable_extension(this->ike_sa,
+ EXT_IKE_FRAGMENTATION);
+ }
+ }
default:
break;
}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 00ca615d8..d91fa5862 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 Tobias Brunner
+ * Copyright (C) 2010-2014 Tobias Brunner
* Copyright (C) 2007 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -77,6 +77,11 @@ struct private_ike_mobike_t {
* additional addresses got updated
*/
bool addresses_updated;
+
+ /**
+ * whether the pending updates counter was increased
+ */
+ bool pending_update;
};
/**
@@ -301,35 +306,61 @@ static void apply_port(host_t *host, host_t *old, u_int16_t port, bool local)
host->set_port(host, port);
}
-METHOD(ike_mobike_t, transmit, void,
+METHOD(ike_mobike_t, transmit, bool,
private_ike_mobike_t *this, packet_t *packet)
{
host_t *me, *other, *me_old, *other_old;
enumerator_t *enumerator;
ike_cfg_t *ike_cfg;
packet_t *copy;
+ int family = AF_UNSPEC;
+ bool found = FALSE;
+
+ me_old = this->ike_sa->get_my_host(this->ike_sa);
+ other_old = this->ike_sa->get_other_host(this->ike_sa);
+ ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
if (!this->check)
{
- return;
+ me = hydra->kernel_interface->get_source_addr(hydra->kernel_interface,
+ other_old, me_old);
+ if (me)
+ {
+ if (me->ip_equals(me, me_old))
+ {
+ charon->sender->send(charon->sender, packet->clone(packet));
+ me->destroy(me);
+ return TRUE;
+ }
+ me->destroy(me);
+ }
+ this->check = TRUE;
}
- me_old = this->ike_sa->get_my_host(this->ike_sa);
- other_old = this->ike_sa->get_other_host(this->ike_sa);
- ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
+ switch (charon->socket->supported_families(charon->socket))
+ {
+ case SOCKET_FAMILY_IPV4:
+ family = AF_INET;
+ break;
+ case SOCKET_FAMILY_IPV6:
+ family = AF_INET6;
+ break;
+ case SOCKET_FAMILY_BOTH:
+ case SOCKET_FAMILY_NONE:
+ break;
+ }
enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, (void**)&other))
{
+ if (family != AF_UNSPEC && other->get_family(other) != family)
+ {
+ continue;
+ }
me = hydra->kernel_interface->get_source_addr(
hydra->kernel_interface, other, NULL);
if (me)
{
- if (me->get_family(me) != other->get_family(other))
- {
- me->destroy(me);
- continue;
- }
/* reuse port for an active address, 4500 otherwise */
apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
other = other->clone(other);
@@ -339,9 +370,11 @@ METHOD(ike_mobike_t, transmit, void,
copy->set_source(copy, me);
copy->set_destination(copy, other);
charon->sender->send(charon->sender, copy);
+ found = TRUE;
}
}
enumerator->destroy(enumerator);
+ return found;
}
METHOD(task_t, build_i, status_t,
@@ -481,9 +514,7 @@ METHOD(task_t, process_i, status_t,
}
else if (message->get_exchange_type(message) == INFORMATIONAL)
{
- u_int32_t updates = this->ike_sa->get_pending_updates(this->ike_sa) - 1;
- this->ike_sa->set_pending_updates(this->ike_sa, updates);
- if (updates > 0)
+ if (this->ike_sa->get_pending_updates(this->ike_sa) > 1)
{
/* newer update queued, ignore this one */
return SUCCESS;
@@ -560,7 +591,6 @@ METHOD(task_t, process_i, status_t,
this->natd = ike_natd_create(this->ike_sa, this->initiator);
}
this->check = FALSE;
- this->ike_sa->set_pending_updates(this->ike_sa, 1);
return NEED_MORE;
}
}
@@ -573,8 +603,12 @@ METHOD(ike_mobike_t, addresses, void,
private_ike_mobike_t *this)
{
this->address = TRUE;
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, roam, void,
@@ -582,8 +616,12 @@ METHOD(ike_mobike_t, roam, void,
{
this->check = TRUE;
this->address = address;
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, dpd, void,
@@ -593,8 +631,12 @@ METHOD(ike_mobike_t, dpd, void,
{
this->natd = ike_natd_create(this->ike_sa, this->initiator);
}
- this->ike_sa->set_pending_updates(this->ike_sa,
+ if (!this->pending_update)
+ {
+ this->pending_update = TRUE;
+ this->ike_sa->set_pending_updates(this->ike_sa,
this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(ike_mobike_t, is_probing, bool,
@@ -603,6 +645,12 @@ METHOD(ike_mobike_t, is_probing, bool,
return this->check;
}
+METHOD(ike_mobike_t, enable_probing, void,
+ private_ike_mobike_t *this)
+{
+ this->check = TRUE;
+}
+
METHOD(task_t, get_type, task_type_t,
private_ike_mobike_t *this)
{
@@ -618,11 +666,21 @@ METHOD(task_t, migrate, void,
{
this->natd->task.migrate(&this->natd->task, ike_sa);
}
+ if (this->pending_update)
+ {
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) + 1);
+ }
}
METHOD(task_t, destroy, void,
private_ike_mobike_t *this)
{
+ if (this->pending_update)
+ {
+ this->ike_sa->set_pending_updates(this->ike_sa,
+ this->ike_sa->get_pending_updates(this->ike_sa) - 1);
+ }
chunk_free(&this->cookie2);
if (this->natd)
{
@@ -650,6 +708,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
.dpd = _dpd,
.transmit = _transmit,
.is_probing = _is_probing,
+ .enable_probing = _enable_probing,
},
.ike_sa = ike_sa,
.initiator = initiator,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.h b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
index b145a9a8b..bb2318c9c 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.h
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.h
@@ -70,8 +70,9 @@ struct ike_mobike_t {
* probing.
*
* @param packet the packet to transmit
+ * @return TRUE if transmitted, FALSE if no path found
*/
- void (*transmit)(ike_mobike_t *this, packet_t *packet);
+ bool (*transmit)(ike_mobike_t *this, packet_t *packet);
/**
* Check if this task is probing for routability.
@@ -79,6 +80,11 @@ struct ike_mobike_t {
* @return TRUE if task is probing
*/
bool (*is_probing)(ike_mobike_t *this);
+
+ /**
+ * Enable probing for routability.
+ */
+ void (*enable_probing)(ike_mobike_t *this);
};
/**